MapSearch = { mapControl: null, defaultPoint: {lat: -41.01379915504413, lng: 172.96875, zoom: 6}, result_container: null, extend: function(selector, data, apiKey){ if (selector){ this.selector = selector; this.listings = data.listings; this.apiKey = apiKey; } var el = $(this.selector || this.defaultSelector); if (window.GMap2){ MapSearch.markerIcon = new GIcon(G_DEFAULT_ICON); MapSearch.markerIcon.image = '/images/map/marker.png'; MapSearch.mapControl = new GMap2(el[0]); MapSearch.mapControl.setCenter(new GLatLng(this.defaultPoint.lat, this.defaultPoint.lng), this.defaultPoint.zoom); MapSearch.mapControl.addControl(new GLargeMapControl3D()); MapSearch.mapControl.enableContinuousZoom(); $.getScript("/javascripts/clusters.js?1234567890", function(){ var markers = []; $.each(MapSearch.listings, function(){ var listing = this; var marker = new GMarker(new GLatLng(listing.latitude, listing.longitude), MapSearch.markerIcon); GEvent.addListener(marker, 'click', function() { MapSearch.showListing(listing); }); markers.push(marker); }); var clusterer = new MarkerClusterer(MapSearch.mapControl, markers); }) } else{ el.append($$('p.loading', $(""), 'Loading...')); $.getScript("http://maps.google.com/maps?file=api&v=2.x&async=2&callback=MapSearch.extend&key=" + encodeURIComponent(this.apiKey)); } }, showListing: function(listing){ if (!MapSearch.result_container){ MapSearch.result_container = $(''); MapSearch.mapControl.getContainer().appendChild(MapSearch.result_container[0]); MapSearch.result_container.find('ul li a.close').live('click', function(){ MapSearch.result_container.hide(); return false; }) } MapSearch.result_container.html('
  • Please wait...
  • '); MapSearch.result_container.load("/listings/" + listing.id + "/result", null, function(){ MapSearch.result_container.find('li').append('Close'); MapSearch.result_container.effect('highlight', {}, 600); }); MapSearch.result_container.show(); } }; ListingMap = { mapControl: null, loadCallbacks: [], defaultPoint: {lat: -40.51379915504413, lng: 172.96875, zoom: 5}, defaultSelector: "#pageMap", onload: function() { for (var i = 0; i < this.loadCallbacks.length; i++){ this.loadCallbacks[i](); } this.loadCallbacks = []; }, extend: function(selector, geolocation, apiKey) { var context = this; var el = $(selector || this.defaultSelector); if (el.length > 0) { var domEl = el.get(0); if (geolocation) domEl.geolocation = geolocation; el.append($$('p.loading', $(""), 'Loading...')); this.loadCallbacks.push(function() { domEl.markerIcon = new GIcon(G_DEFAULT_ICON); domEl.markerIcon.image = '/images/map/marker.png'; domEl.mapControl = new GMap2(domEl); domEl.mapControl.setCenter(new GLatLng(domEl.geolocation.map_latitude || context.defaultPoint.lat, domEl.geolocation.map_longitude || context.defaultPoint.lng), domEl.geolocation.map_zoom || context.defaultPoint.zoom); domEl.marker = new GMarker(new GLatLng(domEl.geolocation.latitude, domEl.geolocation.longitude), {draggable: true, icon: domEl.markerIcon}); domEl.marker.disableDragging(); domEl.mapControl.addOverlay(domEl.marker); context.mapControl = domEl.mapControl; }); if (window.GMap2) this.onload(); else $.getScript("http://maps.google.com/maps?file=api&v=2.x&async=2&callback=ListingMap.onload&key=" + encodeURIComponent(apiKey)); if (!domEl.originalLocation) domEl.originalLocation = geolocation } }, refresh: function(selector) { var context = this; var el = $(selector || this.defaultSelector); var domEl = el.get(0); if (domEl.mapControl){ var listing = ListingEditor.workingListing(); domEl.mapControl.setCenter(new GLatLng(listing.map_latitude || this.defaultPoint.lat, listing.map_longitude || this.defaultPoint.lng), listing.map_zoom || listing.map_zoom); domEl.marker.setPoint(new GLatLng(listing.latitude, listing.longitude)); } else{ setTimeout(function(){ context.refresh(selector); }, 1000); } }, showDefault: function(selector) { var el = $(selector || this.defaultSelector); var domEl = el.get(0); domEl.mapControl.setCenter(new GLatLng(this.defaultPoint.lat, this.defaultPoint.lng)); domEl.mapControl.setZoom(this.defaultPoint.zoom); domEl.marker.setPoint(new GLatLng(this.defaultPoint.lat, this.defaultPoint.lng)); }, edit: function(selector, callback) { var context = this; var onchange = callback; var geolocation = ListingEditor.workingListing(); var el = $(selector || this.defaultSelector); var domEl = el.get(0); if (!domEl.marker){ setTimeout(function(){ context.edit(el, onchange) }, 500); return; } if (geolocation) domEl.geolocation = geolocation; domEl.marker.enableDragging(); domEl.mapControl.addControl(new GLargeMapControl()); domEl.mapControl.setCenter(new GLatLng(domEl.geolocation.map_latitude || context.defaultPoint.lat, domEl.geolocation.map_longitude || context.defaultPoint.lng), domEl.geolocation.map_zoom || context.defaultPoint.zoom); domEl.marker.setPoint(new GLatLng(domEl.geolocation.latitude || context.defaultPoint.lat, domEl.geolocation.longitude || context.defaultPoint.lng)); domEl.marker.openInfoWindow("The map is automatically generated from the street address.

    If it is not showing the correct location, you can manually adjust the marker or map centre by clicking and dragging.", {maxWidth: 400}); GEvent.addListener(domEl.mapControl, 'moveend', function() { var mapCentre = domEl.mapControl.getCenter() ListingEditor.updateSubmission('map_latitude', mapCentre.lat()); ListingEditor.updateSubmission('map_longitude', mapCentre.lng()); if (domEl.geolocation.latitude === 0 && domEl.geolocation.longitude === 0) {{ domEl.marker.setPoint(new GLatLng(domEl.geolocation.map_latitude, domEl.geolocation.map_longitude)); }} if (onchange) onchange(); }); GEvent.addListener(domEl.mapControl, 'zoomend', function() { ListingEditor.updateSubmission('map_zoom', domEl.mapControl.getZoom()); if (onchange) onchange(); }); GEvent.addListener(domEl.marker, 'dragend', function() { var markerCentre = domEl.marker.getLatLng() ListingEditor.updateSubmission('latitude', markerCentre.lat()); ListingEditor.updateSubmission('longitude', markerCentre.lng()); domEl.marker.closeInfoWindow(); if (onchange) onchange(); }); }, cancel: function(selector) { var el = $(selector || this.defaultSelector); var domEl = el.get(0); this.extend(el, domEl.originalLocation); } }; Utils = { getSearchUrl: function(definition, format) { var result = "/listings/find"; if (definition.Location) { result += '/' + encodeURIComponent(definition.Location).replace(/%20/g, '+'); } if (definition.Categories || definition.categories.length > 0) { for (var i = 0; i < definition.categories.length; i++) { result += '/' + encodeURIComponent(definition.categories[i]).replace(/%20/g, '+'); } } if (format){ result += '.' + format; } if (definition.terms) { result += "?terms=" + encodeURIComponent(definition.terms); } if (window.is_portal){ result += (result.indexOf('?') > 0) ? '&' : '?'; result += 'list=all'; } return result; } } SearchSuggestions = { extend: function(s, i) { var insertMode = i; var selector = s; $(function() { var el = $(selector); el.attr("autocomplete","off"); var popup = $$("ul.categories", "suggestions"); var refreshTimer = 0; var hideTimer = 0; var lastRequest = null; var searchButton = el.parent().find("img"); var searchIconUrl = searchButton.attr("src"); var loadingIconUrl = "/images/icons/loading.gif"; var cache = {}; var cueHide = function() { hideTimer = setTimeout(function() { popup.slideUp(200); searchButton.attr("src", searchIconUrl); }, 100); }; var highlight = function(value, term) { return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "$1"); }; var linkUp = function() { if (insertMode){ popup.find('a').click(function() { el[0].value = this.title; setTimeout(function() {el[0].focus()}, 50); return false; }); } }; var cueSearch = function() { if (searchButton.attr("src") != loadingIconUrl) { searchButton.attr("src", loadingIconUrl); } clearTimeout(refreshTimer); refreshTimer = setTimeout(function() { if (el.val() == "") { cueHide(); } else { popup.css({position:"absolute", width:el.width(), top: el.offset().top + el.height() + 6, left: el.offset().left + 10}); lastRequest = "/listings/category_searches.json?count=15&terms=" + encodeURIComponent(el.val()); if (cache[lastRequest]) { popup.html(cache[lastRequest]); popup.slideDown(200); searchButton.attr("src", searchIconUrl); linkUp(); } else { $.getJSON(lastRequest, null, function(data) { if (lastRequest == this.url) { var val = el.val(); popup.empty(); if (!insertMode) { popup.append($$('li.count', $$('a', data[0].count + ' result(s) for ', $$('strong', data[0].terms), {href: Utils.getSearchUrl(data[0])}))); } for (var i = 1; i < data.length; i++){ popup.append($$('li', $$('a', {href: insertMode ? '#' : (Utils.getSearchUrl(data[i])), title: data[i].title}).append(highlight(data[i].title, val)), $$("span", ' (' + data[i].count + ')'))); } popup.slideDown(200); cache[lastRequest] = popup.html(); searchButton.attr("src", searchIconUrl); } linkUp(); }); } } }, 200); }; popup.mousedown(function() { var x = false; setTimeout(function() {clearTimeout(hideTimer);}, 50); }); popup.mouseup(function() { var x = false; cueHide(); }); el.blur(function() { var x = false; cueHide(); }); if (!insertMode){ el.focus(function() { var x = false; if (el.val() != "") cueSearch(); }); } $('body').append(popup); popup.css({position:"absolute", width:el.width(), top: el.offset().top + el.height() + 6, left: el.offset().left + 10}); popup.hide(); el.keydown(function() { cueSearch(); }); }); } }; ListingSearch = { extend: function(element, total) { var el = $(element); var getCount = function() { return el.find("li").not(".more").length - 1; }; var updateSearchUrl = function() { var match = /[\?&]page=([0-9]*)$/.exec(link.attr('href')); if (match){ link.attr('href', link.attr('href').replace(/page=([0-9]*)$/, 'page=' + (parseInt(match[1]) + 1))); } }; var container = el.find("li.more"); var link = container.find("a"); el.append($$('li.loading', $(""), 'Loading...')); el.find("li.loading").hide(); el.after(""); if (getCount() >= total) { el.find("li.more").hide(); } $(function() { if ($("#pageState").val() !== "") { el.html($("#pageState").val()); var count = getCount(); $('#showCount').text(count); } link.click(function() { container.hide(); el.find("li.loading").show(); var start = getCount(); $.get(link.attr('href') + '&partial=true', null, function(content) { $('li.more').before(content); el.find("li.loading").hide(); var count = getCount(); $('#showCount').text(count); updateSearchUrl(); if (count < total) { container.show(); } $("#pageState").val(el.html()); }, "html"); return false; }) }); } }; ModalPopup = { show: function(content) { ModalPopup.prepare(); var overlay = $('#overlay'); var popup = $('#popup'); var container = $('#popup td.container'); container.empty(); container.append(content); popup.show(); overlay.show(); setTimeout(function() { popup.find(":input:first").focus(); }, 200); }, prepare: function() { var overlay = $('#overlay'); var popup = $('#popup'); if (overlay.length == 0) overlay = $("
    ").appendTo('body'); if (popup.length == 0) { popup = $("").appendTo('body'); popup.append("
    "); } popup.hide(); overlay.hide(); }, hide: function() { $('#overlay').hide(); $('#popup').hide(); } }; ListingEditor = { listingResource: new ActiveResource('listing'), submissionResource: new ActiveResource('submission'), listingID: null, originalListing: null, changes: null, locals: {}, editors: {}, isEditing: false, authToken: "", register: function(name, editor) { this.editors[name] = editor; }, applyChange: function(key, value){ this.changes[key] = value; var element = this.findElement(key); if (element) { var editor = this.editors[element.attr('id')]; if (editor){ editor.refresh(false); if (element.attr('id') != 'listingMap'){ element.effect('highlight', {color: '#6bff43'}, 200); } } element.slideDown(100); } }, removeChange: function(key){ delete this.changes[key]; var element = this.findElement(key); this.editors[element.attr('id')].refresh(false); element.effect('highlight', {color: '#ff6868'}, 200); }, findElement: function(key){ for (var name in this.editors){ var editor = this.editors[name]; for (field in editor.fields){ if (editor.fields.hasOwnProperty(field)) { if (key == editor.fields[field].replace(/^.*:/, '')) return $('#' + name) } } } return $('empty'); }, updateSubmission: function(key, value){ var originalValue = this.originalListing[key]; var destination = this.changes; var currentValue = destination[key]; if (value !== originalValue) { destination[key] = value; } else if(currentValue !== undefined){ delete destination[key]; } }, workingListing: function() { var result = {}; var originalListing = this.originalListing; var submission = this.changes; for (var k in originalListing) { if (originalListing.hasOwnProperty(k)) { if (originalListing[k] && originalListing[k].constructor == Array){ // clone array result[k] = []; for (var i = 0; i < originalListing[k].length; i++){ result[k].push(originalListing[k][i]) } } else{ result[k] = originalListing[k]; } } } for (var k in submission) { if (submission.hasOwnProperty(k)) { var value = submission[k] // check for add/remove merge if (value && value.hasOwnProperty('add') && value.add.constructor == Array && result[k].constructor == Array){ for (var i = 0; i < value.add.length; i++){ result[k].push({name: value.add[i]}) } for (var c = 0; c < result[k].length; c++){ for (var i = 0; i < value.remove.length; i++){ if (result[k][c].name == value.remove[i]){ result[k].splice(c, 1); c -= 1; break; } } } } // else overwrite else{ result[k] = value; } } } return result; }, applyEditor: function(callback) { if (this.isEditing) { if (callback) callback(); } else { var context = this; ModalPopup.prepare(); $('.view').hide(); if (this.options['mode'] == 'approve' || this.options['mode'] == 'merge'){ this.showEditor(); if (callback) callback(); } else { $('.loading').show(); if (this.options['mode'] == 'selected'){ this.listingResource.request('new', function(listing) { context.originalListing = listing; context.changes = {id: 'selected'}; $('.loading').hide(); context.showEditor(); if (callback) callback(); }); } else{ this.listingResource.request(context.listingID, function(listing) { context.originalListing = listing; context.changes = {id: listing.id || null}; $('.loading').hide(); context.showEditor(); if (callback) callback(); }); } } this.isEditing = true; } }, showEditor: function(){ // editor loaded if (this.options['mode'] !== "selected"){ ListingMap.edit('#pageMap'); } $('.edit').show(); $('#advertisement').slideUp(400); $('.hidden').slideDown(500); $('a.modify').fadeIn(3000); if ($('#logo, #photo_1, #photo_2, #photo_3').find('a.modify img').length == 0){ $('#logo, #photo_1, #photo_2, #photo_3, #banner').children().not('a').wrap($$('a.modify', {href: '#'})); $('#logo, #photo_1, #photo_2, #photo_3, #banner').find('a:not(.extended)').addClass('extended').attr('rel', 'nozoom').click(function() { ListingEditor.edit(this.parentNode); return false; }); } $.each(this.editors, function() { this.refresh(); }); }, cancel: function() { if (this.options['mode'] == "new"){ window.location = '/'; return; } location.reload(); //this.isEditing = false; //$('.view').show(); //$('.edit').hide(); //$('a.modify').hide(); //$('.hidden').slideUp(500); //$('#banner').slideDown(500); //if (this.options['mode'] != 'approve' || this.options['mode'] == 'merge'){ // this.changes = {}; //} //$.each(this.editors, function() { // this.refresh(); //}); //ListingMap.cancel('#pageMap'); }, reject: function(){ ModalPopup.show("

    Rejecting submission..

    Please wait
    "); ActiveResource.save('submission', {id: this.options['submission_id'], status: -1}, function() { window.location = '/submissions' }); }, save: function() { var context = this; if (this.options['mode'] == "submit" || (this.options['mode'] == "new" && !this.options['can_create'])) return this.submit(); ModalPopup.show("

    Saving changes...

    Please wait
    "); ActiveResource.save('listing', this.changes, function(response) { if (context.options['mode'] == 'selected'){ window.location = '/listings/selected'; } else{ if (context.options['submission_id']){ ActiveResource.save('submission', {id: context.options['submission_id'], listing_id: response.id, status: 1}, function() { window.location = '/listings/' + response.id; }); } else{ if (context.options['mode'] == 'merge'){ ActiveResource.destroy('listing', context.options['other_listing_id'], function(){ window.location = '/listings/' + response.id; }); } else{ window.location = '/listings/' + response.id; } } } }, function(response){ ModalPopup.hide(); $('.view').hide(); $('.edit').show(); alert(JSON.stringify(response)); }); $('.view').show(); $('.edit').hide(); }, upgrade: function(callback, cancelCallback){ var context = this; var editing = this.isEditing; this.applyEditor(function(){ context.editors["premiumService"].show(function(){ context.editors["premiumService"].refresh(); if (callback) callback(); }, function(){ if (!editing) context.cancel(); if (cancelCallback) cancelCallback(); }); }); }, submit: function() { var context = this; var editor = $$("div.editor"); var is_payment = false; var submission = { name: this.options['name'], email_address: this.options['email_address'], phone_number: this.options['phone_number'], postal_address: null, changes: this.changes, listing_id: this.listingID }; var fields = { "Your name": "name", "Email address": "email_address", "Phone number": "phone_number" }; is_payment = this.changes['service_level'] !== undefined && this.changes['service_level'] > 0; if (is_payment){ fields["Postal Address"] = "textarea.address:postal_address" $("

    Purchase Premium Service

    ").appendTo(editor); $("Master Card, Visa and American Express accepted via Paymex").appendTo(editor); } else{ $("Enter details of person submitting information").appendTo(editor); } editor.append(EditorFormatter.fieldTable(fields)); if (is_payment){ $("

    We accept payments by bank transfer, cheque and credit card.
    Payment details are provided on the next page.

    ").appendTo(editor); } editor.append(EditorFormatter.dialogButtons(function() { var uncomplete = editor.find("input:text:not([value])"); if (uncomplete.length > 0){ uncomplete.effect('highlight', {color: 'red'}, 1000); } else { EditorFormatter.saveData(editor, submission); ModalPopup.show("

    Submitting changes...

    Please wait
    "); ActiveResource.save('submission', submission, function(response) { if (is_payment){ window.location = "/submissions/" + response.id + "/pay"; } else{ if (context.listingID && context.listingID > 0) { location.reload(true); } else { window.location = "/"; } } }, function(response){ alert(JSON.stringify(response)); }); } }, function () { ModalPopup.hide(); })); EditorFormatter.applyData(editor, submission); ModalPopup.show(editor); editor.find('#payment_type_credit').val('credit_card'); editor.find('#payment_type_cheque').val('cheque'); editor.find('#payment_type_bank').val('bank_transfer'); }, edit: function(selector, callback, cancel_callback) { var el = $(selector); var editor = this.editors[el.attr('id')]; if (editor) { editor.show(function() { editor.refresh(); if (callback) callback(); }, function(){ if (cancel_callback) cancel_callback(); }); } }, refresh: function(selector){ var el = $(selector); var editor = this.editors[el.attr('id')]; if (editor) { editor.refresh(); } }, extend: function(selector, listingID, options) { this.listingID = listingID; this.options = options || {}; if (this.options['mode'] == 'approve' || this.options['mode'] == 'merge'){ this.listingResource.request(this.listingID, function(listing) { context.originalListing = listing; context.changes = {id: listing.id || null}; }); } var el = $(selector); var context = this; el.append($(" Upgrade ").click(function() { context.upgrade(function(){ if (context.options['mode'] == 'submit') { context.submit(); } }); return false; })); el.append($("").click(function() { context.save(); })); if (context.options['submission_id']){ el.append($("").click(function() { context.reject(); })); } if (this.options['mode'] == 'submit' || (this.options['mode'] == "new" && !this.options['can_create'])){ $("#messages").after(""); } else{ if (this.options['mode'] == 'selected'){ if ($('#messages .bulk_edit').length == 0){ $("#messages").append("
    Warning: Any changes will be applied to all selected listings. Blank fields are ignored. View Selected
    "); } } else{ if ($('#messages .immediate_approval').length == 0){ $("#messages").append("
    You are logged in so your changes will appear immediately.
    "); } } } el.append($(" Loading editor...")); el.append($(" or Cancel").click(function() { context.cancel(); return false; })); el.append($("").click(function() { context.applyEditor(); })); $('#contactDetails div, #otherDetails div, h1').not('div.clear').append($("Modify")); $('#description').append($("[edit description]")); $('#categories').append($("[add category]")); $('a.modify').click(function() { ListingEditor.edit(this.parentNode); return false; }); $('.edit').hide(); $('.loading').hide(); $('a.modify').hide(); if (this.options['mode'] == 'approve' || this.options['mode'] == 'merge'){ $('.approve').show(); } $(function(){ $('body').append($$("iframe", { name: "uploader", id: "uploader" })); $('#uploader')[0].callback = function(editor, value){ context.updateSubmission(editor + '_id', value); ModalPopup.hide(); context.editors[editor].refresh(true); } }) $(function(){ if (context.options["mode"] == "new" || context.options["mode"] == "selected"){ jQuery.fx.off = true; setTimeout(function(){ jQuery.fx.off = false; }, 4000); context.applyEditor(function(){ if (context.options["mode"] == "new"){ //if (context.options["area"]){ // context.updateSubmission('area_name', context.options["area"]); //} $(function(){ context.edit('#name', null, function(){ window.location = "/"; }); }) } }); } }) } } EditorFormatter = { fieldTable: function(fields) { var table = $("
    "); var container = table.find("tbody"); for (var key in fields) { if (fields.hasOwnProperty(key)) { var value = fields[key]; if (value){ var selector = "input"; if (value.indexOf(':') > 0) { selector = value.split(/:/)[0]; value = value.split(/:/)[1]; } if (selector != 'hidden'){ var newRow = $("").appendTo(container); newRow.addClass(value); var input = $$(selector == 'checkbox' ? 'input' : selector); newRow.find('th').text(key); if (selector == 'checkbox'){ input.attr('name', value).filter('input').attr("type", "checkbox"); } else{ input.attr('name', value).filter('input').attr("type", "text"); } newRow.find('td').append(input); } } } } return table; }, dialogButtons: function(okFunction, cancelFunction) { var container = $("
    OK").appendTo(container).click(function() { okFunction(); }); $("  or Cancel").appendTo(container).click(function() { cancelFunction(); return false; }); return container; }, applyData: function(selector, data) { var el = $(selector); if (!data) data = ListingEditor.workingListing(); var items = el.find(':input, :checkbox').not('button'); items.each(function() { if (this.type == 'checkbox'){ this.checked = data[this.getAttribute("name")] || ""; } else{ this.value = data[this.getAttribute("name")] || ""; } }); items = items.not('textarea'); if (items.length > 0){ items.eq(items.length - 1).keydown(function(e){ if (e.keyCode == 13) el.find('button.save').click(); }) } }, saveData: function(selector, data) { var items = $(selector).find('input:text, input:checkbox, input:radio:checked, textarea, select'); items.each(function() { var key = this.getAttribute("name"); var newValue = null; if (this.type == 'checkbox'){ newValue = this.checked; } else{ newValue = this.value.replace(/\r\n/g, "\n").replace(/\r/g, "\n") || null; } if (data){ data[key] = newValue } else{ ListingEditor.updateSubmission(key, newValue) } }); return data; }, setInfo: function(selector, info, useHeading) { var customHeading = null; var el = $(selector).find('p').eq(0); var data = ListingEditor.workingListing(); el.empty(); var heading = $(selector).find("h2"); for (var key in info) { if (info.hasOwnProperty(key)) { var keys = info[key].split('|'); var value = ""; for (var e = 0; e < keys.length; e++){ if (data[keys[e]]){ if (value.length > 0) value += " "; value += data[keys[e]]; } } if (value && value.constructor == Array) value = value.join(', ') if (value && $.trim(value.toString()) !== "") { if (useHeading) { heading.text(value); useHeading = false; } else { if (el.text().length > 0) el.append("
    "); if (info.constructor !== Array) { el.append($$('strong', key + ':')); el.append(" "); } var lines = value.split(/\n/g); el.append(document.createTextNode(lines[0])); for (var i = 1; i < lines.length; i++) { el.append("
    ", document.createTextNode(lines[i])); } } } } } if (useHeading) heading.text($(selector).attr('title')); } }; ListingSubmissions = { approve: function(id){ var resource = new ActiveResource('submission'); resource.action(id, 'approve', function(response){ $('#submission_' + id).slideUp(200); }); }, reject: function(id){ var resource = new ActiveResource('submission'); resource.update(id, {status: -1}, function(response){ $('#submission_' + response.id).slideUp(200); }); } }; ListingSelection = { refresh: function(){ var resource = new ActiveResource("listing"); $('#selection ul').load('/listings/selected?partial=true'); resource.request("selected", function(response) { if (response.length > 0) $('#selection').slideDown(100).effect('highlight', {}, 300); else $('#selection').slideUp(100); $('#selection h2 span.title').text(pluralize(response.length, 'listing') + " selected"); }); }, addToList: function(callback){ var context = this; var editor = $$("div.editor"); var resource = new ActiveResource('list'); ModalPopup.show("

    Loading...

    Please wait
    "); var checkitems = resource.index(function(lists){ $("

    Add Listings to Contact List

    ").appendTo(editor); items = $$('ul.categorySuggestions').appendTo(editor); for (var i = 0; i < lists.length; i++){ items.append($$('li', lists[i].name, {title: lists[i].name})); } items.find('li').click(function(){ $(this).toggleClass("selected"); }); $$('div', "Add new: ", $$('input.new')).appendTo(editor); editor.append(EditorFormatter.dialogButtons(function() { var selected_items = []; items.find('li.selected').each(function(){ selected_items.push(this.title); }); if (editor.find('input.new').val().length > 0){ selected_items.push(editor.find('input.new').val()); } var resource = new ActiveResource("listing"); resource.update("selected", {lists: {add: selected_items}}, function() { ModalPopup.hide(); }); ModalPopup.show("

    Saving changes...

    Please wait
    "); if (callback) callback(); }, function () { ModalPopup.hide(); })); ModalPopup.show(editor); }) }, removeFromList: function(callback){ var context = this; var editor = $$("div.editor"); var resource = new ActiveResource('list'); ModalPopup.show("

    Loading...

    Please wait
    "); var checkitems = resource.index(function(lists){ $("

    Remove Listings from Contact List

    ").appendTo(editor); items = $$('ul.categorySuggestions').appendTo(editor); for (var i = 0; i < lists.length; i++){ items.append($$('li', lists[i].name, {title: lists[i].name})); } items.find('li').click(function(){ $(this).toggleClass("selected"); }); editor.append(EditorFormatter.dialogButtons(function() { var selected_items = []; items.find('li.selected').each(function(){ selected_items.push(this.title); }); var resource = new ActiveResource("listing"); resource.update("selected", {lists: {remove: selected_items}}, function() { ModalPopup.hide(); }); ModalPopup.show("

    Saving changes...

    Please wait
    "); if (callback) callback(); }, function () { ModalPopup.hide(); })); ModalPopup.show(editor); }) }, addToCategory: function(callback){ var context = this; var editor = $$("div.editor"); $("

    Add Listings to Category

    ").appendTo(editor); search_box = $$('input.search').appendTo(editor); editor.append(EditorFormatter.dialogButtons(function() { var resource = new ActiveResource("listing"); resource.update("selected", {categories: {add: [search_box.val()]}}, function() { ModalPopup.hide(); }); ModalPopup.show("

    Saving changes...

    Please wait
    "); if (callback) callback(); }, function () { ModalPopup.hide(); })); ModalPopup.show(editor); SearchSuggestions.extend(search_box, true); }, removeFromCategory: function(callback){ var context = this; var editor = $$("div.editor"); $("

    Remove Listings from Category

    ").appendTo(editor); search_box = $$('input.search').appendTo(editor); editor.append(EditorFormatter.dialogButtons(function() { var resource = new ActiveResource("listing"); resource.update("selected", {categories: {remove: [search_box.val()]}}, function() { ModalPopup.hide(); }); ModalPopup.show("

    Saving changes...

    Please wait
    "); if (callback) callback(); }, function () { ModalPopup.hide(); })); ModalPopup.show(editor); SearchSuggestions.extend(search_box, true); } }; jQuery.autocomplete = function(input, options) { // Create a link to self var me = this; // Create jQuery object for input element var $input = $(input).attr("autocomplete", "off"); // Apply inputClass if necessary if (options.inputClass) $input.addClass(options.inputClass); // Create results var results = document.createElement("div"); // Create jQuery object for results var $results = $(results); $results.hide().addClass(options.resultsClass).css("position", "absolute"); if( options.width > 0 ) $results.css("width", options.width); // Add to body element $("body").append(results); input.autocompleter = me; var timeout = null; var prev = ""; var active = -1; var cache = {}; var keyb = false; var hasFocus = false; var lastKeyPressCode = null; // flush cache function flushCache(){ cache = {}; cache.data = {}; cache.length = 0; }; // flush cache flushCache(); // if there is a data array supplied if( options.data != null ){ var sFirstChar = "", stMatchSets = {}, row = []; // no url was specified, we need to adjust the cache length to make sure it fits the local data store if( typeof options.url != "string" ) options.cacheLength = 1; // loop through the array and create a lookup structure for( var i=0; i < options.data.length; i++ ){ // if row is a string, make an array otherwise just reference the array row = ((typeof options.data[i] == "string") ? [options.data[i]] : options.data[i]); // if the length is zero, don't add to list if( row[0].length > 0 ){ // get the first character sFirstChar = row[0].substring(0, 1).toLowerCase(); // if no lookup array for this character exists, look it up now if( !stMatchSets[sFirstChar] ) stMatchSets[sFirstChar] = []; // if the match is a string stMatchSets[sFirstChar].push(row); } } // add the data items to the cache for( var k in stMatchSets ){ // increase the cache size options.cacheLength++; // add to the cache addToCache(k, stMatchSets[k]); } } $input .keydown(function(e) { // track last key pressed lastKeyPressCode = e.keyCode; switch(e.keyCode) { case 38: // up e.preventDefault(); moveSelect(-1); break; case 40: // down e.preventDefault(); moveSelect(1); break; case 9: // tab case 13: // return if( selectCurrent() ){ // make sure to blur off the current field $input.get(0).blur(); e.preventDefault(); } break; default: active = -1; if (timeout) clearTimeout(timeout); timeout = setTimeout(function(){onChange();}, options.delay); break; } }) .focus(function(){ // track whether the field has focus, we shouldn't process any results if the field no longer has focus hasFocus = true; }) .blur(function() { // track whether the field has focus hasFocus = false; hideResults(); }); hideResultsNow(); function onChange() { // ignore if the following keys are pressed: [del] [shift] [capslock] if( lastKeyPressCode == 46 || (lastKeyPressCode > 8 && lastKeyPressCode < 32) ) return $results.hide(); var v = $input.val(); if (v == prev) return; prev = v; if (v.length >= options.minChars) { $input.addClass(options.loadingClass); requestData(v); } else { $input.removeClass(options.loadingClass); $results.hide(); } }; function moveSelect(step) { var lis = $("li", results); if (!lis) return; active += step; if (active < 0) { active = 0; } else if (active >= lis.size()) { active = lis.size() - 1; } lis.removeClass("ac_over"); $(lis[active]).addClass("ac_over"); // Weird behaviour in IE // if (lis[active] && lis[active].scrollIntoView) { // lis[active].scrollIntoView(false); // } }; function selectCurrent() { var li = $("li.ac_over", results)[0]; if (!li) { var $li = $("li", results); if (options.selectOnly) { if ($li.length == 1) li = $li[0]; } else if (options.selectFirst) { li = $li[0]; } } if (li) { selectItem(li); return true; } else { return false; } }; function selectItem(li) { if (!li) { li = document.createElement("li"); li.extra = []; li.selectValue = ""; } var v = $.trim(li.selectValue ? li.selectValue : li.innerHTML); input.lastSelected = v; prev = v; $results.html(""); $input.val(v); hideResultsNow(); //if (options.onItemSelect) setTimeout(function() { options.onItemSelect(li) }, 1); }; // selects a portion of the input string function createSelection(start, end){ // get a reference to the input element var field = $input.get(0); if( field.createTextRange ){ var selRange = field.createTextRange(); selRange.collapse(true); selRange.moveStart("character", start); selRange.moveEnd("character", end); selRange.select(); } else if( field.setSelectionRange ){ field.setSelectionRange(start, end); } else { if( field.selectionStart ){ field.selectionStart = start; field.selectionEnd = end; } } field.focus(); }; // fills in the input box w/the first match (assumed to be the best match) function autoFill(sValue){ // if the last user key pressed was backspace, don't autofill if( lastKeyPressCode != 8 ){ // fill in the value (keep the case the user has typed) $input.val($input.val() + sValue.substring(prev.length)); // select the portion of the value not typed by the user (so the next character will erase) createSelection(prev.length, sValue.length); } }; function showResults() { // get the position of the input field right now (in case the DOM is shifted) var pos = findPos(input); // either use the specified width, or autocalculate based on form element var iWidth = (options.width > 0) ? options.width : $input.width(); // reposition $results.css({ width: parseInt(iWidth) + "px", top: (pos.y + input.offsetHeight) + "px", left: pos.x + "px" }).show(); }; function hideResults() { if (timeout) clearTimeout(timeout); timeout = setTimeout(hideResultsNow, 200); }; function hideResultsNow() { if (timeout) clearTimeout(timeout); $input.removeClass(options.loadingClass); if ($results.is(":visible")) { $results.hide(); } if (options.mustMatch) { var v = $input.val(); if (v != input.lastSelected) { selectItem(null); } } if (options.onItemSelect) setTimeout(function() { options.onItemSelect() }, 1); }; function receiveData(q, data) { if (data) { $input.removeClass(options.loadingClass); results.innerHTML = ""; // if the field no longer has focus or if there are no matches, do not display the drop down if( !hasFocus || data.length == 0 ) return hideResultsNow(); if ($.browser.msie) { // we put a styled iframe behind the calendar so HTML SELECT elements don't show through $results.append(document.createElement('iframe')); } results.appendChild(dataToDom(data)); // autofill in the complete box w/the first match as long as the user hasn't entered in more data if( options.autoFill && ($input.val().toLowerCase() == q.toLowerCase()) ) autoFill(data[0][0]); showResults(); } else { hideResultsNow(); } }; function parseData(data) { if (!data) return null; var parsed = []; var rows = data.split(options.lineSeparator); for (var i=0; i < rows.length; i++) { var row = $.trim(rows[i]); if (row) { parsed[parsed.length] = row.split(options.cellSeparator); } } return parsed; }; function dataToDom(data) { var ul = document.createElement("ul"); var num = data.length; // limited results to a max number if( (options.maxItemsToShow > 0) && (options.maxItemsToShow < num) ) num = options.maxItemsToShow; for (var i=0; i < num; i++) { var row = data[i]; if (!row) continue; var li = document.createElement("li"); if (options.formatItem) { li.innerHTML = options.formatItem(row, i, num); li.selectValue = row[0]; } else { li.innerHTML = row[0]; li.selectValue = row[0]; } var extra = null; if (row.length > 1) { extra = []; for (var j=1; j < row.length; j++) { extra[extra.length] = row[j]; } } li.extra = extra; ul.appendChild(li); $(li).hover( function() { $("li", ul).removeClass("ac_over"); $(this).addClass("ac_over"); active = $("li", ul).indexOf($(this).get(0)); }, function() { $(this).removeClass("ac_over"); } ).click(function(e) { e.preventDefault(); e.stopPropagation(); selectItem(this) }); } return ul; }; function requestData(q) { if (!options.matchCase) q = q.toLowerCase(); var data = options.cacheLength ? loadFromCache(q) : null; // recieve the cached data if (data) { receiveData(q, data); // if an AJAX url has been supplied, try loading the data now } else if( (typeof options.url == "string") && (options.url.length > 0) ){ $.get(makeUrl(q), function(data) { data = parseData(data); addToCache(q, data); receiveData(q, data); }); // if there's been no data found, remove the loading class } else { $input.removeClass(options.loadingClass); } }; function makeUrl(q) { var url = options.url + "?q=" + encodeURI(q); for (var i in options.extraParams) { url += "&" + i + "=" + encodeURI(options.extraParams[i]); } return url; }; function loadFromCache(q) { if (!q) return null; if (cache.data[q]) return cache.data[q]; if (options.matchSubset) { for (var i = q.length - 1; i >= options.minChars; i--) { var qs = q.substr(0, i); var c = cache.data[qs]; if (c) { var csub = []; for (var j = 0; j < c.length; j++) { var x = c[j]; var x0 = x[0]; if (matchSubset(x0, q)) { csub[csub.length] = x; } } return csub; } } } return null; }; function matchSubset(s, sub) { if (!options.matchCase) s = s.toLowerCase(); var i = s.indexOf(sub); if (i == -1) return false; return i == 0 || options.matchContains; }; this.flushCache = function() { flushCache(); }; this.setExtraParams = function(p) { options.extraParams = p; }; this.findValue = function(){ var q = $input.val(); if (!options.matchCase) q = q.toLowerCase(); var data = options.cacheLength ? loadFromCache(q) : null; if (data) { findValueCallback(q, data); } else if( (typeof options.url == "string") && (options.url.length > 0) ){ $.get(makeUrl(q), function(data) { data = parseData(data) addToCache(q, data); findValueCallback(q, data); }); } else { // no matches findValueCallback(q, null); } }; this.hideResults = function(){ hideResultsNow(); }; function findValueCallback(q, data){ if (data) $input.removeClass(options.loadingClass); var num = (data) ? data.length : 0; var li = null; for (var i=0; i < num; i++) { var row = data[i]; if( row[0].toLowerCase() == q.toLowerCase() ){ li = document.createElement("li"); if (options.formatItem) { li.innerHTML = options.formatItem(row, i, num); li.selectValue = row[0]; } else { li.innerHTML = row[0]; li.selectValue = row[0]; } var extra = null; if( row.length > 1 ){ extra = []; for (var j=1; j < row.length; j++) { extra[extra.length] = row[j]; } } li.extra = extra; } } if( options.onFindValue ) setTimeout(function() { options.onFindValue(li) }, 1); } function addToCache(q, data) { if (!data || !q || !options.cacheLength) return; if (!cache.length || cache.length > options.cacheLength) { flushCache(); cache.length++; } else if (!cache[q]) { cache.length++; } cache.data[q] = data; }; function findPos(obj) { var curleft = obj.offsetLeft || 0; var curtop = obj.offsetTop || 0; while (obj = obj.offsetParent) { curleft += obj.offsetLeft curtop += obj.offsetTop } return {x:curleft,y:curtop}; } }; var ListingEmail = { send: function(listing_id, options){ var editor = $$("div.editor"); $("

    Send Email

    ").appendTo(editor); editor.append(EditorFormatter.fieldTable({'Your Name': 'name', 'Your Email Address': 'email_address'})); var input = $$("textarea.description", {rows: 10, cols: 25, name: 'body'}).appendTo(editor); editor.append(EditorFormatter.dialogButtons(function() { var resource = new ActiveResource('message'); var message = EditorFormatter.saveData(editor, {}); resource.createThrough('listing', listing_id, message, function(){ ModalPopup.hide(); $("
    Your email was sent successfully. Any replies will be sent to " + message.email_address + ".
    ").appendTo("#messages").effect('highlight', {}, 200); $("#advertisement").hide(); }); ModalPopup.hide(); ModalPopup.show("

    Sending email...

    Please wait
    "); }, function () { ModalPopup.hide(); })); ModalPopup.show(editor); } }; jQuery.fn.autocomplete = function(url, options, data) { // Make sure options exists options = options || {}; // Set url as option options.url = url; // set some bulk local data options.data = ((typeof data == "object") && (data.constructor == Array)) ? data : null; // Set default values for required options options.inputClass = options.inputClass || "ac_input"; options.resultsClass = options.resultsClass || "ac_results"; options.lineSeparator = options.lineSeparator || "\n"; options.cellSeparator = options.cellSeparator || "|"; options.minChars = options.minChars || 1; options.delay = options.delay || 400; options.matchCase = options.matchCase || 0; options.matchSubset = options.matchSubset || 1; options.matchContains = options.matchContains || 0; options.cacheLength = options.cacheLength || 1; options.mustMatch = options.mustMatch || 0; options.extraParams = options.extraParams || {}; options.loadingClass = options.loadingClass || "ac_loading"; options.selectFirst = options.selectFirst || false; options.selectOnly = options.selectOnly || false; options.maxItemsToShow = options.maxItemsToShow || -1; options.autoFill = options.autoFill || false; options.width = parseInt(options.width, 10) || 0; this.each(function() { var input = this; new jQuery.autocomplete(input, options); }); // Don't break the chain return this; } jQuery.fn.autocompleteArray = function(data, options) { return this.autocomplete(null, options, data); } jQuery.fn.indexOf = function(e){ for( var i=0; i