diff --git a/app/assets/javascripts/lib/date.format.js b/app/assets/javascripts/lib/date.format.js new file mode 100644 index 00000000..3eb3d1cc --- /dev/null +++ b/app/assets/javascripts/lib/date.format.js @@ -0,0 +1,126 @@ +/* + * Date Format 1.2.3 + * (c) 2007-2009 Steven Levithan + * MIT license + * + * Includes enhancements by Scott Trenda + * and Kris Kowal + * + * Accepts a date, a mask, or a date and a mask. + * Returns a formatted version of the given date. + * The date defaults to the current date/time. + * The mask defaults to dateFormat.masks.default. + */ + +var dateFormat = function () { + var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g, + timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g, + timezoneClip = /[^-+\dA-Z]/g, + pad = function (val, len) { + val = String(val); + len = len || 2; + while (val.length < len) val = "0" + val; + return val; + }; + + // Regexes and supporting functions are cached through closure + return function (date, mask, utc) { + var dF = dateFormat; + + // You can't provide utc if you skip other args (use the "UTC:" mask prefix) + if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) { + mask = date; + date = undefined; + } + + // Passing date through Date applies Date.parse, if necessary + date = date ? new Date(date) : new Date; + if (isNaN(date)) throw SyntaxError("invalid date"); + + mask = String(dF.masks[mask] || mask || dF.masks["default"]); + + // Allow setting the utc argument via the mask + if (mask.slice(0, 4) == "UTC:") { + mask = mask.slice(4); + utc = true; + } + + var _ = utc ? "getUTC" : "get", + d = date[_ + "Date"](), + D = date[_ + "Day"](), + m = date[_ + "Month"](), + y = date[_ + "FullYear"](), + H = date[_ + "Hours"](), + M = date[_ + "Minutes"](), + s = date[_ + "Seconds"](), + L = date[_ + "Milliseconds"](), + o = utc ? 0 : date.getTimezoneOffset(), + flags = { + d: d, + dd: pad(d), + ddd: dF.i18n.dayNames[D], + dddd: dF.i18n.dayNames[D + 7], + m: m + 1, + mm: pad(m + 1), + mmm: dF.i18n.monthNames[m], + mmmm: dF.i18n.monthNames[m + 12], + yy: String(y).slice(2), + yyyy: y, + h: H % 12 || 12, + hh: pad(H % 12 || 12), + H: H, + HH: pad(H), + M: M, + MM: pad(M), + s: s, + ss: pad(s), + l: pad(L, 3), + L: pad(L > 99 ? Math.round(L / 10) : L), + t: H < 12 ? "a" : "p", + tt: H < 12 ? "am" : "pm", + T: H < 12 ? "A" : "P", + TT: H < 12 ? "AM" : "PM", + Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""), + o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4), + S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10] + }; + + return mask.replace(token, function ($0) { + return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1); + }); + }; +}(); + +// Some common format strings +dateFormat.masks = { + "default": "ddd mmm dd yyyy HH:MM:ss", + shortDate: "m/d/yy", + mediumDate: "mmm d, yyyy", + longDate: "mmmm d, yyyy", + fullDate: "dddd, mmmm d, yyyy", + shortTime: "h:MM TT", + mediumTime: "h:MM:ss TT", + longTime: "h:MM:ss TT Z", + isoDate: "yyyy / mm / dd", + isoTime: "HH:MM:ss", + isoDateTime: "yyyy-mm-dd'T'HH:MM:ss", + isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'" +}; + +// Internationalization strings +dateFormat.i18n = { + dayNames: [ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" + ], + monthNames: [ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", + "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" + ] +}; + +// For convenience... +Date.prototype.format = function (mask, utc) { + return dateFormat(this, mask, utc); +}; + diff --git a/app/assets/javascripts/lib/datepicker.js b/app/assets/javascripts/lib/datepicker.js new file mode 100644 index 00000000..7c8d4b03 --- /dev/null +++ b/app/assets/javascripts/lib/datepicker.js @@ -0,0 +1,891 @@ +/** + * + * Date picker + * Author: Stefan Petre www.eyecon.ro + * + * Dual licensed under the MIT and GPL licenses + * + */ +(function ($) { + var DatePicker = function () { + var ids = {}, + views = { + years: 'datepickerViewYears', + moths: 'datepickerViewMonths', + days: 'datepickerViewDays' + }, + tpl = { + wrapper: '
', + head: [ + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '
<%=prev%><%=next%>
<%=week%><%=day1%><%=day2%><%=day3%><%=day4%><%=day5%><%=day6%><%=day7%>
' + ], + space : '
', + days: [ + '', + '', + '<%=weeks[0].week%>', + '<%=weeks[0].days[0].text%>', + '<%=weeks[0].days[1].text%>', + '<%=weeks[0].days[2].text%>', + '<%=weeks[0].days[3].text%>', + '<%=weeks[0].days[4].text%>', + '<%=weeks[0].days[5].text%>', + '<%=weeks[0].days[6].text%>', + '', + '', + '<%=weeks[1].week%>', + '<%=weeks[1].days[0].text%>', + '<%=weeks[1].days[1].text%>', + '<%=weeks[1].days[2].text%>', + '<%=weeks[1].days[3].text%>', + '<%=weeks[1].days[4].text%>', + '<%=weeks[1].days[5].text%>', + '<%=weeks[1].days[6].text%>', + '', + '', + '<%=weeks[2].week%>', + '<%=weeks[2].days[0].text%>', + '<%=weeks[2].days[1].text%>', + '<%=weeks[2].days[2].text%>', + '<%=weeks[2].days[3].text%>', + '<%=weeks[2].days[4].text%>', + '<%=weeks[2].days[5].text%>', + '<%=weeks[2].days[6].text%>', + '', + '', + '<%=weeks[3].week%>', + '<%=weeks[3].days[0].text%>', + '<%=weeks[3].days[1].text%>', + '<%=weeks[3].days[2].text%>', + '<%=weeks[3].days[3].text%>', + '<%=weeks[3].days[4].text%>', + '<%=weeks[3].days[5].text%>', + '<%=weeks[3].days[6].text%>', + '', + '', + '<%=weeks[4].week%>', + '<%=weeks[4].days[0].text%>', + '<%=weeks[4].days[1].text%>', + '<%=weeks[4].days[2].text%>', + '<%=weeks[4].days[3].text%>', + '<%=weeks[4].days[4].text%>', + '<%=weeks[4].days[5].text%>', + '<%=weeks[4].days[6].text%>', + '', + '', + '<%=weeks[5].week%>', + '<%=weeks[5].days[0].text%>', + '<%=weeks[5].days[1].text%>', + '<%=weeks[5].days[2].text%>', + '<%=weeks[5].days[3].text%>', + '<%=weeks[5].days[4].text%>', + '<%=weeks[5].days[5].text%>', + '<%=weeks[5].days[6].text%>', + '', + '' + ], + months: [ + '', + '', + '<%=data[0]%>', + '<%=data[1]%>', + '<%=data[2]%>', + '<%=data[3]%>', + '', + '', + '<%=data[4]%>', + '<%=data[5]%>', + '<%=data[6]%>', + '<%=data[7]%>', + '', + '', + '<%=data[8]%>', + '<%=data[9]%>', + '<%=data[10]%>', + '<%=data[11]%>', + '', + '' + ] + }, + defaults = { + flat: false, + starts: 1, + prev: '◀', + next: '▶', + lastSel: false, + mode: 'single', + view: 'days', + calendars: 1, + format: 'Y-m-d', + position: 'bottom', + eventName: 'click', + onRender: function(){return {};}, + onChange: function(){return true;}, + onShow: function(){return true;}, + onBeforeShow: function(){return true;}, + onHide: function(){return true;}, + locale: { + days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], + daysShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], + daysMin: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], + months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + monthsShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], + weekMin: 'wk' + } + }, + fill = function(el) { + var options = $(el).data('datepicker'); + var cal = $(el); + var currentCal = Math.floor(options.calendars/2), date, data, dow, month, cnt = 0, week, days, indic, indic2, html, tblCal; + cal.find('td>table tbody').remove(); + for (var i = 0; i < options.calendars; i++) { + date = new Date(options.current); + date.addMonths(-currentCal + i); + tblCal = cal.find('table').eq(i+1); + switch (tblCal[0].className) { + case 'datepickerViewDays': + dow = formatDate(date, 'B, Y'); + break; + case 'datepickerViewMonths': + dow = date.getFullYear(); + break; + case 'datepickerViewYears': + dow = (date.getFullYear()-6) + ' - ' + (date.getFullYear()+5); + break; + } + tblCal.find('thead tr:first th:eq(1) span').text(dow); + dow = date.getFullYear()-6; + data = { + data: [], + className: 'datepickerYears' + } + for ( var j = 0; j < 12; j++) { + data.data.push(dow + j); + } + html = tmpl(tpl.months.join(''), data); + date.setDate(1); + data = {weeks:[], test: 10}; + month = date.getMonth(); + var dow = (date.getDay() - options.starts) % 7; + date.addDays(-(dow + (dow < 0 ? 7 : 0))); + week = -1; + cnt = 0; + while (cnt < 42) { + indic = parseInt(cnt/7,10); + indic2 = cnt%7; + if (!data.weeks[indic]) { + week = date.getWeekNumber(); + data.weeks[indic] = { + week: week, + days: [] + }; + } + data.weeks[indic].days[indic2] = { + text: date.getDate(), + classname: [] + }; + if (month != date.getMonth()) { + data.weeks[indic].days[indic2].classname.push('datepickerNotInMonth'); + } + if (date.getDay() == 0) { + data.weeks[indic].days[indic2].classname.push('datepickerSunday'); + } + if (date.getDay() == 6) { + data.weeks[indic].days[indic2].classname.push('datepickerSaturday'); + } + var fromUser = options.onRender(date); + var val = date.valueOf(); + if (fromUser.selected || options.date == val || $.inArray(val, options.date) > -1 || (options.mode == 'range' && val >= options.date[0] && val <= options.date[1])) { + data.weeks[indic].days[indic2].classname.push('datepickerSelected'); + } + if (fromUser.disabled) { + data.weeks[indic].days[indic2].classname.push('datepickerDisabled'); + } + if (fromUser.className) { + data.weeks[indic].days[indic2].classname.push(fromUser.className); + } + data.weeks[indic].days[indic2].classname = data.weeks[indic].days[indic2].classname.join(' '); + cnt++; + date.addDays(1); + } + html = tmpl(tpl.days.join(''), data) + html; + data = { + data: options.locale.monthsShort, + className: 'datepickerMonths' + }; + html = tmpl(tpl.months.join(''), data) + html; + tblCal.append(html); + } + }, + parseDate = function (date, format) { + if (date.constructor == Date) { + return new Date(date); + } + var parts = date.split(/\W+/); + var against = format.split(/\W+/), d, m, y, h, min, now = new Date(); + for (var i = 0; i < parts.length; i++) { + switch (against[i]) { + case 'd': + case 'e': + d = parseInt(parts[i],10); + break; + case 'm': + m = parseInt(parts[i], 10)-1; + break; + case 'Y': + case 'y': + y = parseInt(parts[i], 10); + y += y > 100 ? 0 : (y < 29 ? 2000 : 1900); + break; + case 'H': + case 'I': + case 'k': + case 'l': + h = parseInt(parts[i], 10); + break; + case 'P': + case 'p': + if (/pm/i.test(parts[i]) && h < 12) { + h += 12; + } else if (/am/i.test(parts[i]) && h >= 12) { + h -= 12; + } + break; + case 'M': + min = parseInt(parts[i], 10); + break; + } + } + return new Date( + y === undefined ? now.getFullYear() : y, + m === undefined ? now.getMonth() : m, + d === undefined ? now.getDate() : d, + h === undefined ? now.getHours() : h, + min === undefined ? now.getMinutes() : min, + 0 + ); + }, + formatDate = function(date, format) { + var m = date.getMonth(); + var d = date.getDate(); + var y = date.getFullYear(); + var wn = date.getWeekNumber(); + var w = date.getDay(); + var s = {}; + var hr = date.getHours(); + var pm = (hr >= 12); + var ir = (pm) ? (hr - 12) : hr; + var dy = date.getDayOfYear(); + if (ir == 0) { + ir = 12; + } + var min = date.getMinutes(); + var sec = date.getSeconds(); + var parts = format.split(''), part; + for ( var i = 0; i < parts.length; i++ ) { + part = parts[i]; + switch (parts[i]) { + case 'a': + part = date.getDayName(); + break; + case 'A': + part = date.getDayName(true); + break; + case 'b': + part = date.getMonthName(); + break; + case 'B': + part = date.getMonthName(true); + break; + case 'C': + part = 1 + Math.floor(y / 100); + break; + case 'd': + part = (d < 10) ? ("0" + d) : d; + break; + case 'e': + part = d; + break; + case 'H': + part = (hr < 10) ? ("0" + hr) : hr; + break; + case 'I': + part = (ir < 10) ? ("0" + ir) : ir; + break; + case 'j': + part = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; + break; + case 'k': + part = hr; + break; + case 'l': + part = ir; + break; + case 'm': + part = (m < 9) ? ("0" + (1+m)) : (1+m); + break; + case 'M': + part = (min < 10) ? ("0" + min) : min; + break; + case 'p': + case 'P': + part = pm ? "PM" : "AM"; + break; + case 's': + part = Math.floor(date.getTime() / 1000); + break; + case 'S': + part = (sec < 10) ? ("0" + sec) : sec; + break; + case 'u': + part = w + 1; + break; + case 'w': + part = w; + break; + case 'y': + part = ('' + y).substr(2, 2); + break; + case 'Y': + part = y; + break; + } + parts[i] = part; + } + return parts.join(''); + }, + extendDate = function(options) { + if (Date.prototype.tempDate) { + return; + } + Date.prototype.tempDate = null; + Date.prototype.months = options.months; + Date.prototype.monthsShort = options.monthsShort; + Date.prototype.days = options.days; + Date.prototype.daysShort = options.daysShort; + Date.prototype.getMonthName = function(fullName) { + return this[fullName ? 'months' : 'monthsShort'][this.getMonth()]; + }; + Date.prototype.getDayName = function(fullName) { + return this[fullName ? 'days' : 'daysShort'][this.getDay()]; + }; + Date.prototype.addDays = function (n) { + this.setDate(this.getDate() + n); + this.tempDate = this.getDate(); + }; + Date.prototype.addMonths = function (n) { + if (this.tempDate == null) { + this.tempDate = this.getDate(); + } + this.setDate(1); + this.setMonth(this.getMonth() + n); + this.setDate(Math.min(this.tempDate, this.getMaxDays())); + }; + Date.prototype.addYears = function (n) { + if (this.tempDate == null) { + this.tempDate = this.getDate(); + } + this.setDate(1); + this.setFullYear(this.getFullYear() + n); + this.setDate(Math.min(this.tempDate, this.getMaxDays())); + }; + Date.prototype.getMaxDays = function() { + var tmpDate = new Date(Date.parse(this)), + d = 28, m; + m = tmpDate.getMonth(); + d = 28; + while (tmpDate.getMonth() == m) { + d ++; + tmpDate.setDate(d); + } + return d - 1; + }; + Date.prototype.getFirstDay = function() { + var tmpDate = new Date(Date.parse(this)); + tmpDate.setDate(1); + return tmpDate.getDay(); + }; + Date.prototype.getWeekNumber = function() { + var tempDate = new Date(this); + tempDate.setDate(tempDate.getDate() - (tempDate.getDay() + 6) % 7 + 3); + var dms = tempDate.valueOf(); + tempDate.setMonth(0); + tempDate.setDate(4); + return Math.round((dms - tempDate.valueOf()) / (604800000)) + 1; + }; + Date.prototype.getDayOfYear = function() { + var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0); + var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0); + var time = now - then; + return Math.floor(time / 24*60*60*1000); + }; + }, + layout = function (el) { + var options = $(el).data('datepicker'); + var cal = $('#' + options.id); + if (!options.extraHeight) { + var divs = $(el).find('div'); + //options.extraHeight = divs.get(0).offsetHeight + divs.get(1).offsetHeight; + //options.extraWidth = divs.get(2).offsetWidth + divs.get(3).offsetWidth; + } + var tbl = cal.find('table:first').get(0); + var width = tbl.offsetWidth; + var height = tbl.offsetHeight; + cal.css({ + width: width + options.extraWidth + 'px', + height: height + options.extraHeight + 'px' + }).find('div.datepickerContainer').css({ + width: width + 'px', + height: height + 'px' + }); + }, + click = function(ev) { + if ($(ev.target).is('span')) { + ev.target = ev.target.parentNode; + } + var el = $(ev.target); + if (el.is('a')) { + ev.target.blur(); + if (el.hasClass('datepickerDisabled')) { + return false; + } + var options = $(this).data('datepicker'); + var parentEl = el.parent(); + var tblEl = parentEl.parent().parent().parent(); + var tblIndex = $('table', this).index(tblEl.get(0)) - 1; + var tmp = new Date(options.current); + var changed = false; + var fillIt = false; + if (parentEl.is('th')) { + if (parentEl.hasClass('datepickerWeek') && options.mode == 'range' && !parentEl.next().hasClass('datepickerDisabled')) { + var val = parseInt(parentEl.next().text(), 10); + tmp.addMonths(tblIndex - Math.floor(options.calendars/2)); + if (parentEl.next().hasClass('datepickerNotInMonth')) { + tmp.addMonths(val > 15 ? -1 : 1); + } + tmp.setDate(val); + options.date[0] = (tmp.setHours(0,0,0,0)).valueOf(); + tmp.setHours(23,59,59,0); + tmp.addDays(6); + options.date[1] = tmp.valueOf(); + fillIt = true; + changed = true; + options.lastSel = false; + } else if (parentEl.hasClass('datepickerMonth')) { + tmp.addMonths(tblIndex - Math.floor(options.calendars/2)); + switch (tblEl.get(0).className) { + case 'datepickerViewDays': + tblEl.get(0).className = 'datepickerViewMonths'; + el.find('span').text(tmp.getFullYear()); + break; + case 'datepickerViewMonths': + tblEl.get(0).className = 'datepickerViewYears'; + el.find('span').text((tmp.getFullYear()-6) + ' - ' + (tmp.getFullYear()+5)); + break; + case 'datepickerViewYears': + tblEl.get(0).className = 'datepickerViewDays'; + el.find('span').text(formatDate(tmp, 'B, Y')); + break; + } + } else if (parentEl.parent().parent().is('thead')) { + switch (tblEl.get(0).className) { + case 'datepickerViewDays': + options.current.addMonths(parentEl.hasClass('datepickerGoPrev') ? -1 : 1); + break; + case 'datepickerViewMonths': + options.current.addYears(parentEl.hasClass('datepickerGoPrev') ? -1 : 1); + break; + case 'datepickerViewYears': + options.current.addYears(parentEl.hasClass('datepickerGoPrev') ? -12 : 12); + break; + } + fillIt = true; + } + } else if (parentEl.is('td') && !parentEl.hasClass('datepickerDisabled')) { + switch (tblEl.get(0).className) { + case 'datepickerViewMonths': + options.current.setMonth(tblEl.find('tbody.datepickerMonths td').index(parentEl)); + options.current.setFullYear(parseInt(tblEl.find('thead th.datepickerMonth span').text(), 10)); + options.current.addMonths(Math.floor(options.calendars/2) - tblIndex); + tblEl.get(0).className = 'datepickerViewDays'; + break; + case 'datepickerViewYears': + options.current.setFullYear(parseInt(el.text(), 10)); + tblEl.get(0).className = 'datepickerViewMonths'; + break; + default: + var val = parseInt(el.text(), 10); + tmp.addMonths(tblIndex - Math.floor(options.calendars/2)); + if (parentEl.hasClass('datepickerNotInMonth')) { + tmp.addMonths(val > 15 ? -1 : 1); + } + tmp.setDate(val); + switch (options.mode) { + case 'multiple': + val = (tmp.setHours(0,0,0,0)).valueOf(); + if ($.inArray(val, options.date) > -1) { + $.each(options.date, function(nr, dat){ + if (dat == val) { + options.date.splice(nr,1); + return false; + } + }); + } else { + options.date.push(val); + } + break; + case 'range': + if (!options.lastSel) { + options.date[0] = (tmp.setHours(0,0,0,0)).valueOf(); + } + val = (tmp.setHours(23,59,59,0)).valueOf(); + if (val < options.date[0]) { + options.date[1] = options.date[0] + 86399000; + options.date[0] = val - 86399000; + } else { + options.date[1] = val; + } + options.lastSel = !options.lastSel; + break; + default: + options.date = tmp.valueOf(); + break; + } + break; + } + fillIt = true; + changed = true; + } + if (fillIt) { + fill(this); + } + if (changed) { + options.onChange.apply(this, prepareDate(options)); + } + } + return false; + }, + prepareDate = function (options) { + var tmp; + if (options.mode == 'single') { + tmp = new Date(options.date); + return [formatDate(tmp, options.format), tmp, options.el]; + } else { + tmp = [[],[], options.el]; + $.each(options.date, function(nr, val){ + var date = new Date(val); + tmp[0].push(formatDate(date, options.format)); + tmp[1].push(date); + }); + return tmp; + } + }, + getViewport = function () { + var m = document.compatMode == 'CSS1Compat'; + return { + l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft), + t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop), + w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth), + h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight) + }; + }, + isChildOf = function(parentEl, el, container) { + if (parentEl == el) { + return true; + } + if (parentEl.contains) { + return parentEl.contains(el); + } + if ( parentEl.compareDocumentPosition ) { + return !!(parentEl.compareDocumentPosition(el) & 16); + } + var prEl = el.parentNode; + while(prEl && prEl != container) { + if (prEl == parentEl) + return true; + prEl = prEl.parentNode; + } + return false; + }, + show = function (ev) { + var cal = $('#' + $(this).data('datepickerId')); + if (!cal.is(':visible')) { + var calEl = cal.get(0); + fill(calEl); + var options = cal.data('datepicker'); + options.onBeforeShow.apply(this, [cal.get(0)]); + var pos = $(this).offset(); + var viewPort = getViewport(); + var top = pos.top; + var left = pos.left; + var oldDisplay = $.curCSS(calEl, 'display'); + cal.css({ + visibility: 'hidden', + display: 'block' + }); + layout(calEl); + switch (options.position){ + case 'top': + top -= calEl.offsetHeight; + break; + case 'left': + left -= calEl.offsetWidth; + break; + case 'right': + left += this.offsetWidth; + break; + case 'bottom': + top += this.offsetHeight; + break; + } + if (top + calEl.offsetHeight > viewPort.t + viewPort.h) { + top = pos.top - calEl.offsetHeight; + } + if (top < viewPort.t) { + top = pos.top + this.offsetHeight + calEl.offsetHeight; + } + if (left + calEl.offsetWidth > viewPort.l + viewPort.w) { + left = pos.left - calEl.offsetWidth; + } + if (left < viewPort.l) { + left = pos.left + this.offsetWidth + } + cal.css({ + visibility: 'visible', + display: 'block', + top: top + 'px', + left: left + 'px' + }); + if (options.onShow.apply(this, [cal.get(0)]) != false) { + cal.show(); + } + $(document).bind('mousedown', {cal: cal, trigger: this}, hide); + } + return false; + }, + hide = function (ev) { + if (ev.target != ev.data.trigger && !isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) { + if (ev.data.cal.data('datepicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) { + ev.data.cal.hide(); + } + $(document).unbind('mousedown', hide); + } + }; + return { + init: function(options){ + options = $.extend({}, defaults, options||{}); + extendDate(options.locale); + options.calendars = Math.max(1, parseInt(options.calendars,10)||1); + options.mode = /single|multiple|range/.test(options.mode) ? options.mode : 'single'; + return this.each(function(){ + if (!$(this).data('datepicker')) { + options.el = this; + if (options.date.constructor == String) { + options.date = parseDate(options.date, options.format); + options.date.setHours(0,0,0,0); + } + if (options.mode != 'single') { + if (options.date.constructor != Array) { + options.date = [options.date.valueOf()]; + if (options.mode == 'range') { + options.date.push(((new Date(options.date[0])).setHours(23,59,59,0)).valueOf()); + } + } else { + for (var i = 0; i < options.date.length; i++) { + options.date[i] = (parseDate(options.date[i], options.format).setHours(0,0,0,0)).valueOf(); + } + if (options.mode == 'range') { + options.date[1] = ((new Date(options.date[1])).setHours(23,59,59,0)).valueOf(); + } + } + } else { + options.date = options.date.valueOf(); + } + if (!options.current) { + options.current = new Date(); + } else { + options.current = parseDate(options.current, options.format); + } + options.current.setDate(1); + options.current.setHours(0,0,0,0); + var id = 'datepicker_' + parseInt(Math.random() * 1000), cnt; + options.id = id; + $(this).data('datepickerId', options.id); + var cal = $(tpl.wrapper).attr('id', id).bind('click', click).data('datepicker', options); + if (options.className) { + cal.addClass(options.className); + } + var html = ''; + for (var i = 0; i < options.calendars; i++) { + cnt = options.starts; + if (i > 0) { + html += tpl.space; + } + html += tmpl(tpl.head.join(''), { + week: options.locale.weekMin, + prev: options.prev, + next: options.next, + day1: options.locale.daysMin[(cnt++)%7], + day2: options.locale.daysMin[(cnt++)%7], + day3: options.locale.daysMin[(cnt++)%7], + day4: options.locale.daysMin[(cnt++)%7], + day5: options.locale.daysMin[(cnt++)%7], + day6: options.locale.daysMin[(cnt++)%7], + day7: options.locale.daysMin[(cnt++)%7] + }); + } + cal + .find('tr:first').append(html) + .find('table').addClass(views[options.view]); + fill(cal.get(0)); + if (options.flat) { + cal.appendTo(this).show().css('position', 'relative'); + layout(cal.get(0)); + } else { + cal.appendTo(document.body); + $(this).bind(options.eventName, show); + } + } + }); + }, + showPicker: function() { + return this.each( function () { + if ($(this).data('datepickerId')) { + show.apply(this); + } + }); + }, + hidePicker: function() { + return this.each( function () { + if ($(this).data('datepickerId')) { + $('#' + $(this).data('datepickerId')).hide(); + } + }); + }, + setDate: function(date, shiftTo){ + return this.each(function(){ + if ($(this).data('datepickerId')) { + var cal = $('#' + $(this).data('datepickerId')); + var options = cal.data('datepicker'); + options.date = date; + if (options.date.constructor == String) { + options.date = parseDate(options.date, options.format); + options.date.setHours(0,0,0,0); + } + if (options.mode != 'single') { + if (options.date.constructor != Array) { + options.date = [options.date.valueOf()]; + if (options.mode == 'range') { + options.date.push(((new Date(options.date[0])).setHours(23,59,59,0)).valueOf()); + } + } else { + for (var i = 0; i < options.date.length; i++) { + options.date[i] = (parseDate(options.date[i], options.format).setHours(0,0,0,0)).valueOf(); + } + if (options.mode == 'range') { + options.date[1] = ((new Date(options.date[1])).setHours(23,59,59,0)).valueOf(); + } + } + } else { + options.date = options.date.valueOf(); + } + if (shiftTo) { + options.current = new Date (options.mode != 'single' ? options.date[0] : options.date); + } + fill(cal.get(0)); + } + }); + }, + getDate: function(formated) { + if (this.size() > 0) { + return prepareDate($('#' + $(this).data('datepickerId')).data('datepicker'))[formated ? 0 : 1]; + } + }, + clear: function(){ + return this.each(function(){ + if ($(this).data('datepickerId')) { + var cal = $('#' + $(this).data('datepickerId')); + var options = cal.data('datepicker'); + if (options.mode != 'single') { + options.date = []; + fill(cal.get(0)); + } + } + }); + }, + fixLayout: function(){ + return this.each(function(){ + if ($(this).data('datepickerId')) { + var cal = $('#' + $(this).data('datepickerId')); + var options = cal.data('datepicker'); + if (options.flat) { + layout(cal.get(0)); + } + } + }); + } + }; + }(); + $.fn.extend({ + DatePicker: DatePicker.init, + DatePickerHide: DatePicker.hidePicker, + DatePickerShow: DatePicker.showPicker, + DatePickerSetDate: DatePicker.setDate, + DatePickerGetDate: DatePicker.getDate, + DatePickerClear: DatePicker.clear, + DatePickerLayout: DatePicker.fixLayout + }); +})(jQuery); + +(function(){ + var cache = {}; + + this.tmpl = function tmpl(str, data){ + // Figure out if we're getting a template, or if we need to + // load the template - and be sure to cache the result. + var fn = !/\W/.test(str) ? + cache[str] = cache[str] || + tmpl(document.getElementById(str).innerHTML) : + + // Generate a reusable function that will serve as a template + // generator (and which will be cached). + new Function("obj", + "var p=[],print=function(){p.push.apply(p,arguments);};" + + + // Introduce the data as local variables using with(){} + "with(obj){p.push('" + + + // Convert the template into pure JavaScript + str + .replace(/[\r\t\n]/g, " ") + .split("<%").join("\t") + .replace(/((^|%>)[^\t]*)'/g, "$1\r") + .replace(/\t=(.*?)%>/g, "',$1,'") + .split("\t").join("');") + .split("%>").join("p.push('") + .split("\r").join("\\'") + + "');}return p.join('');"); + + // Provide some basic currying to the user + return data ? fn( data ) : fn; + }; +})(); \ No newline at end of file diff --git a/app/assets/stylesheets/lib/datepicker.css b/app/assets/stylesheets/lib/datepicker.css new file mode 100644 index 00000000..2487c921 --- /dev/null +++ b/app/assets/stylesheets/lib/datepicker.css @@ -0,0 +1,205 @@ +div.datepicker { + position: relative; + font-family: Arial, Helvetica, sans-serif; + font-size: 12px; + height: 147px; + cursor: default; + display: none; +} +.datepickerContainer { + padding: 10px; + margin: 0 auto; +} +/* +.datepickerBorderT { + position: absolute; + left: 10px; + top: 0; + right: 10px; + height: 10px; + background: url(../images/datepicker_t.png); +} +.datepickerBorderB { + position: absolute; + left: 10px; + bottom: 0; + right: 10px; + height: 10px; + background: url(../images/datepicker_b.png); +} +.datepickerBorderL { + position: absolute; + left: 0; + bottom: 10px; + top: 10px; + width: 10px; + background: url(../images/datepicker_l.png); +} +.datepickerBorderR { + position: absolute; + right: 0; + bottom: 10px; + top: 10px; + width: 10px; + background: url(../images/datepicker_r.png); +} +.datepickerBorderTL { + position: absolute; + top: 0; + left: 0; + width: 10px; + height: 10px; + background: url(../images/datepicker_tl.png); +} +.datepickerBorderTR { + position: absolute; + top: 0; + right: 0; + width: 10px; + height: 10px; + background: url(../images/datepicker_tr.png); +} +.datepickerBorderBL { + position: absolute; + bottom: 0; + left: 0; + width: 10px; + height: 10px; + background: url(../images/datepicker_bl.png); +} +.datepickerBorderBR { + position: absolute; + bottom: 0; + right: 0; + width: 10px; + height: 10px; + background: url(../images/datepicker_br.png); +} +*/ +.datepickerHidden { + display: none; +} +div.datepicker table { + width: 260px; + border-collapse:collapse; +} +div.datepicker a { + text-decoration: none; + cursor: default; + outline: none; +} +div.datepicker table td { + text-align: right; + padding: 0; + margin: 0; +} +div.datepicker th { + text-align: center; + color: #999; + font-weight: normal; +} +div.datepicker tbody th { + /*text-align: left;*/ +} +div.datepicker tbody a { + display: block; + width: 100%; + text-align: center; +} +.datepickerWeek a { + color: #F60; +} +.datepickerWeek a:hover { + color: #FC0 !important; +} +.datepickerDays a { + width: 20px; + line-height: 16px; + height: 16px; + padding-right: 2px; +} +.datepickerYears a, +.datepickerMonths a{ + width: 44px; + line-height: 36px; + height: 36px; + text-align: center; +} +td.datepickerNotInMonth a { + color: #666; +} +tbody.datepickerDays td.datepickerSelected{ + background: #0088CC; +} +tbody.datepickerDays td.datepickerSelected a{ + color: #FFF; +} +tbody.datepickerDays td.datepickerNotInMonth.datepickerSelected { + background: #17384d; +} +tbody.datepickerYears td.datepickerSelected, +tbody.datepickerMonths td.datepickerSelected{ + background: #17384d; +} +div.datepicker a:hover, +div.datepicker a:hover { + color: #88c5eb; +} +div.datepicker td.datepickerNotInMonth a:hover { + color: #999; +} +div.datepicker tbody th { + /*text-align: left;*/ +} +.datepickerSpace div { + width: 20px; +} +.datepickerGoNext a, +.datepickerGoPrev a, +.datepickerMonth a { + text-align: center; + height: 20px; + line-height: 20px; +} +.datepickerGoNext a { + float: right; + width: 20px; +} +.datepickerGoPrev a { + float: left; + width: 20px; +} +table.datepickerViewDays tbody.datepickerMonths, +table.datepickerViewDays tbody.datepickerYears { + display: none; +} +table.datepickerViewMonths tbody.datepickerDays, +table.datepickerViewMonths tbody.datepickerYears, +table.datepickerViewMonths tr.datepickerDoW { + display: none; +} +table.datepickerViewYears tbody.datepickerDays, +table.datepickerViewYears tbody.datepickerMonths, +table.datepickerViewYears tr.datepickerDoW { + display: none; +} +td.datepickerDisabled a, +td.datepickerDisabled.datepickerNotInMonth a{ + color: #333; +} +td.datepickerDisabled a:hover { + color: #333; +} +td.datepickerSpecial a { + background: #700; +} +td.datepickerSpecial.datepickerSelected a { + background: #a00; +} + +/*Layout*/ +#widgetCalendar { + height: 0; + overflow: hidden; + position: relative; +} \ No newline at end of file diff --git a/app/assets/stylesheets/widget.css b/app/assets/stylesheets/widget.css index b0e3568d..f1c4d615 100644 --- a/app/assets/stylesheets/widget.css +++ b/app/assets/stylesheets/widget.css @@ -63,28 +63,86 @@ } .file-upload { position:relative; + overflow: hidden; } .file-upload .file-name { - display: inline-block; - margin: 0 0 5px 5px; white-space: nowrap; - width: 140px; + overflow: hidden; + border-style: solid; + border-width: 1px 1px 1px 0; + border-color: #CCC; + display: inline-block; + float: left; + padding: 4px 10px; + height: 18px; + line-height: 18px; + -webkit-border-radius: 0 3px 3px 0; + -moz-border-radius: 0 3px 3px 0; + border-radius: 0 3px 3px 0; + text-align: left; + margin: 0; + width: 182px; } .file-upload .upload { margin:0; padding:0; position:absolute; - top:0; + top: 0; left:0; opacity:.0; - filter: alpha(opacity=100); + font-size: 60px; + left: -595px/9; + filter: alpha(opacity: 0); + outline: none; } .file-upload .upload:focus { position:absolute; } .upload-picture { - margin-right: 5px; + margin-bottom: 5px; + text-align: center; + width: 276px; + overflow: hidden; + height: 90px; +} +.upload-picture img { + left: 0; + margin-top: -15%; + width: 100%; +} +.widget-box .widgetInfo { + display: inline-block; + text-align: center; + width: 255px; + margin : 0px 0 5px; + padding: 5px 10px; +} +.file-upload .input-medium { + border-radius: 3px 3px 3px 3px !important; + width: 267px; + position: relative; + z-index: 5; } #widget-link table { margin-bottom:0 +} +/*Date*/ +.showDate { + border-style: solid; + border-width: 1px 0 1px 1px; + border-color: #CCC; + display: inline-block; + float: left; + padding: 4px 10px; + height: 18px; + line-height: 18px; + -webkit-border-radius: 3px 0 0 3px; + -moz-border-radius: 3px 0 0 3px; + border-radius: 3px 0 0 3px; + text-align: center; +} +.calendarInput { + position: absolute; + visibility: hidden; + left: 11px; } \ No newline at end of file diff --git a/app/controllers/admin/ad_banners_controller.rb b/app/controllers/admin/ad_banners_controller.rb index 614a75fa..95ce7e7c 100644 --- a/app/controllers/admin/ad_banners_controller.rb +++ b/app/controllers/admin/ad_banners_controller.rb @@ -10,11 +10,14 @@ class Admin::AdBannersController < ApplicationController end def show - @ad_banner = AdBanner.find(params[:id]) + @ad_banners = AdBanner.all + @active = AdBanner.find(params[:id]) + render :action => 'index' end def new - @ad_banner = AdBanner.new + @ad_banners = AdBanner.all + render :action => 'index',:params => 'new' end def create @@ -36,8 +39,13 @@ class Admin::AdBannersController < ApplicationController redirect_to admin_ad_banners_url end + def destroy_ad_image + + end + def index @ad_banners = AdBanner.all + @active = @ad_banners.first end end \ No newline at end of file diff --git a/app/controllers/admin/ad_images_controller.rb b/app/controllers/admin/ad_images_controller.rb new file mode 100644 index 00000000..3fb681da --- /dev/null +++ b/app/controllers/admin/ad_images_controller.rb @@ -0,0 +1,47 @@ +class Admin::AdImagesController < ApplicationController + layout 'new_admin' + before_filter :authenticate_user! + before_filter :is_admin? + + def edit + @ad_banner = AdBanner.find params[:ad_banner_id] + @ad_image = @ad_banner.ad_images.find params[:id] + end + + def update + @ad_banner = AdBanner.find params[:ad_banner_id] + @ad_image = AdImage.find params[:id] + @ad_image.update_attributes(params[:ad_image]) + @ad_image.to_save = true + @ad_image.save! + redirect_to admin_ad_banner_path @ad_banner + end + + def new + @ad_image =AdImage.new + #render :action => 'new',:url=> {:ad_banner_id => params.has_key?(:ad_banner_id)? params[:ad_banner_id],nil} + end + + def create + @ad_banner = AdBanner.find params[:ad_banner][:id] + ad_image = AdImage.new params[:ad_image] + ad_image.to_save = true + @ad_banner.ad_images << ad_image + + if @ad_banner.save! + redirect_to admin_ad_banner_path @ad_banner + end + + end + + def destroy + @ad_banner = AdBanner.find params[:ad_banner_id] + @ad_image = @ad_banner.ad_images.find params[:id] + if @ad_image.destroy + flash[:notice] = t('admin.success_destroy_ad_image') + redirect_to admin_ad_banner_path @ad_banner + end + end + + +end diff --git a/app/controllers/gridfs_controller.rb b/app/controllers/gridfs_controller.rb index 8a95a581..4be7ec17 100644 --- a/app/controllers/gridfs_controller.rb +++ b/app/controllers/gridfs_controller.rb @@ -3,7 +3,7 @@ require 'mongo' class GridfsController < ActionController::Metal def serve - gridfs_path = env["PATH_INFO"].gsub("/gridfs/", "") + gridfs_path = env["PATH_INFO"].gsub("/gridfs/", "").force_encoding("UTF-8") begin gridfs_file = Mongo::GridFileSystem.new(Mongoid.database).open(gridfs_path, 'r') self.response_body = gridfs_file.read diff --git a/app/helpers/admin/ad_banner_helper.rb b/app/helpers/admin/ad_banner_helper.rb index 0621df38..2de0504b 100644 --- a/app/helpers/admin/ad_banner_helper.rb +++ b/app/helpers/admin/ad_banner_helper.rb @@ -1,2 +1,34 @@ module Admin::AdBannerHelper + def preview_block(ad_banner) + res ='' + #same code as in frontend backend parser + if ad_banner + res << "" + res << "
" + printable_ad_images = [] + ad_banner.ad_images.each do |ad_image| + if ad_image.display? + ad_image.weight.times do + printable_ad_images << ad_image + end + end + end + + printable_ad_images.shuffle! + printable_ad_images.each do |ad_image| #TODO Need Reflact + res << "" + end + res << "
" + res.html_safe + end + end + end \ No newline at end of file diff --git a/app/helpers/admin/ad_images_helper.rb b/app/helpers/admin/ad_images_helper.rb new file mode 100644 index 00000000..1f2422fc --- /dev/null +++ b/app/helpers/admin/ad_images_helper.rb @@ -0,0 +1,7 @@ +module Admin::AdImagesHelper + + def active_when_default_locale_eq locale + locale.to_sym == I18n.default_locale ? 'active': '' + end + +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 558129c7..f1a57fbd 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -2,6 +2,12 @@ module ApplicationHelper FLASH_NOTICE_KEYS = [:error, :notice, :warning] + def site_valid_locales_default_head + index = @site_valid_locales.rindex I18n.default_locale.to_s + shift_out = @site_valid_locales.shift(index) + @site_valid_locales += shift_out + end + def colorize_in_use_locale(locale) @site_in_use_locales.include?(locale)? 'green' : 'red' end diff --git a/app/models/ad_banner.rb b/app/models/ad_banner.rb index 0a2928b3..3e09280f 100644 --- a/app/models/ad_banner.rb +++ b/app/models/ad_banner.rb @@ -4,41 +4,32 @@ class AdBanner include Mongoid::MultiParameterAttributes field :title - field :picture_position - field :post_date,type: Date - field :unpost_date,type: Date - field :context - field :direct_to_after_click,type: Boolean + field :transition_sec,type: Integer field :ad_fx #TODO Design should explain - - + before_save :save_or_destroy - - embeds_many :ad_images, :cascade_callbacks => true + validates_uniqueness_of :title + has_many :ad_images , dependent: :delete FX_TYPES = ["blindX","blindY","blindZ","cover","curtainX","curtainY","fade","fadeZoom","growX","growY","scrollUp","scrollDown","scrollLeft","scrollRight","scrollHorz","scrollVert","shuffle","slideX","slideY","toss","turnUp","turnDown","turnLeft","turnRight","uncover","wipe","zoom"] - def display? - if (self.post_date <= Date.today && (self.unpost_date.nil? || self.unpost_date>= Date.today)) - return true - end - return false - end + + # def new_ad_images(*attrs) + # debugger + # a=1 + # attrs[0].each do |attr| #Loop by JSs,Themes,Imgs + # unless attr[:file].nil? + # self.ad_images << AdImage.new(attr) + # end + # end + # end - def new_ad_images=(*attrs) - attrs[0].each do |attr| #Loop by JSs,Themes,Imgs - unless attr[:file].nil? - self.ad_images << AdImage.new(attr) - end - end - end - - def existing_ad_images=(*attrs) - attrs[0].each do |attr| #Loop by JSs,Themes,Imgs - ad_image = self.ad_images.find attr[0] - ad_image.update_attributes(attr[1]) - end - end + # def existing_ad_images=(*attrs) + # attrs[0].each do |attr| #Loop by JSs,Themes,Imgs + # ad_image = self.ad_images.find attr[0] + # ad_image.update_attributes(attr[1]) + # end + # end def save_or_destroy self.ad_images.each do |ad_image| diff --git a/app/models/ad_image.rb b/app/models/ad_image.rb index 5d06d798..3eb63511 100644 --- a/app/models/ad_image.rb +++ b/app/models/ad_image.rb @@ -3,19 +3,46 @@ class AdImage include Mongoid::Timestamps mount_uploader :file, ImageUploader + + has_one :title, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy + has_one :context, :class_name => "I18nVariable", :as => :language_value, :autosave => true, :dependent => :destroy - field :time_to_next #Weight - field :picture_intro - field :out_link - field :link_open + field :direct_to_after_click,type: Boolean + + field :weight ,type: Integer ,default: 1 + field :out_link #the link itself + field :link_open #how will the link be opened + LINK_OPEN_TYPES = ["new_window","local"] + + field :post_date,type: Date + field :unpost_date,type: Date field :to_save, :type => Boolean field :to_destroy, :type => Boolean - - LINK_OPEN_TYPES = ["new_window","local"] + + belongs_to :ad_banner + + # validates_numericality_of :weight, greater_than_or_equal_to: 1,less_than_or_equal_to: 10 + # validates_format_of :out_link, with: /(http:\/\/.*|)/ ,:message => 'Need a valid URL' + # validates_presence_of :post_date,:message => 'Need a valid post date' + attr_reader :parse_post_date,:parse_unpost_date + + def parse_post_date=(att) + self.post_date = (Date.parse att rescue nil) + end - embedded_in :ad_banner + def parse_unpost_date=(att) + self.unpost_date = (Date.parse att rescue nil) + end + + def display? + if (self.post_date <= Date.today && (self.unpost_date.nil? || self.unpost_date>= Date.today) rescue false) + return true + end + return false + end + def get_delay_time time = '' diff --git a/app/views/admin/ad_banners/_ad_banner.html.erb b/app/views/admin/ad_banners/_ad_banner.html.erb deleted file mode 100644 index 787a03ed..00000000 --- a/app/views/admin/ad_banners/_ad_banner.html.erb +++ /dev/null @@ -1,11 +0,0 @@ - - - <%= location %> - - > - - <%= link_to (ad_image.picture_intro || t("untitled")),'' %> - <%= start_date %> - <%= end_date.nil?? t('form.date_unlimited'): end_date %> - <%= style %> - \ No newline at end of file diff --git a/app/views/admin/ad_banners/_ad_banner_tab.html.erb b/app/views/admin/ad_banners/_ad_banner_tab.html.erb new file mode 100644 index 00000000..78645ba7 --- /dev/null +++ b/app/views/admin/ad_banners/_ad_banner_tab.html.erb @@ -0,0 +1,18 @@ + +
" id=<%= ad_banner_tab.title %>> +

尺寸:

+ + <%= form_for ad_banner_tab,:url=> admin_ad_banner_path(ad_banner_tab),:method => :put,:class=>"input-medium" do |f| -%> + <%= f.label :ad_fx, t('admin.ad_fx') %> + <%= f.select :ad_fx ,AdBanner::FX_TYPES %> + <%= f.submit %> + <%= f.submit 'Cancel',:type=>'reset' %> + <%= f.text_field :transition_sec,:placeholder=>"3秒請輸入3000",:class=> "span3" %> +
+ <%= render :partial => "ad_image_update", :collection => ad_banner_tab.ad_images,:as => :ad_image,:locals=>{:ad_banner => ad_banner_tab} %> + <%#= render :partial => 'new_add_banner_file', :object => ad_banner_tab.ad_images.build, :locals => { :field_name => "new_ad_images[]", :f => f, :classes => "r_destroy" } %> + <%= link_to 'Add AdImage',new_admin_ad_banner_ad_image_path(ad_banner_tab) %> +
+ <% end -%> + <%= preview_block ad_banner_tab %> +
diff --git a/app/views/admin/ad_banners/_ad_image.html.erb b/app/views/admin/ad_banners/_ad_image.html.erb deleted file mode 100644 index e724a47f..00000000 --- a/app/views/admin/ad_banners/_ad_image.html.erb +++ /dev/null @@ -1,8 +0,0 @@ -
- <%= image_tag ad_image.file %> -

- Time to next: <%= ad_image.time_to_next %> - Intro: <%= ad_image.picture_intro %> - Out Link <%= link_to ad_image.out_link %> by <%= ad_image.link_open %> -

-
diff --git a/app/views/admin/ad_banners/_ad_image_form.html.erb b/app/views/admin/ad_banners/_ad_image_form.html.erb deleted file mode 100644 index 3a153d47..00000000 --- a/app/views/admin/ad_banners/_ad_image_form.html.erb +++ /dev/null @@ -1,5 +0,0 @@ -Time: <%= f.text_field :time_to_next ,:class=> 'ad_time'%> -Link:<%= f.text_field :out_link ,:class=> 'ad_out_link'%> -Open Type <%= f.select :link_open ,AdImage::LINK_OPEN_TYPES %> - -<%= f.hidden_field :to_save %> \ No newline at end of file diff --git a/app/views/admin/ad_banners/_ad_image_show.html.erb b/app/views/admin/ad_banners/_ad_image_show.html.erb deleted file mode 100644 index e724a47f..00000000 --- a/app/views/admin/ad_banners/_ad_image_show.html.erb +++ /dev/null @@ -1,8 +0,0 @@ -
- <%= image_tag ad_image.file %> -

- Time to next: <%= ad_image.time_to_next %> - Intro: <%= ad_image.picture_intro %> - Out Link <%= link_to ad_image.out_link %> by <%= ad_image.link_open %> -

-
diff --git a/app/views/admin/ad_banners/_ad_image_update.html.erb b/app/views/admin/ad_banners/_ad_image_update.html.erb index e3d53b15..366d370d 100644 --- a/app/views/admin/ad_banners/_ad_image_update.html.erb +++ b/app/views/admin/ad_banners/_ad_image_update.html.erb @@ -1,9 +1,12 @@ -<%= fields_for "ad_banner[existing_ad_images][#{ad_image.id}]", ad_image do |f| %> - <%= image_tag ad_image.file %> -
- Destroy?<%= f.check_box :to_destroy %> - <%= render :partial => "ad_image_form", :locals => { :f => f } %> -
-<% end %> - +
  • + <%= image_tag ad_image.file %> +

    + <%= ad_image.display? ? '[Showing]' : '[NotShawing]' %> + <%= "#{ad_image.post_date ||'NeedReset' }~#{ad_image.unpost_date || 'NeedReset'}" %> +

    +

    + <%= link_to 'Edit',edit_admin_ad_banner_ad_image_path(ad_banner,ad_image),:class => 'btn btn-primary' %> + <%= link_to 'Del',admin_ad_banner_ad_image_path(ad_banner,ad_image),:class => 'btn',:method => :delete,:confirm => t('sure?') %> +

    +
  • diff --git a/app/views/admin/ad_banners/_form.html.erb b/app/views/admin/ad_banners/_form.html.erb deleted file mode 100644 index c29d9aef..00000000 --- a/app/views/admin/ad_banners/_form.html.erb +++ /dev/null @@ -1,53 +0,0 @@ -<% content_for :page_specific_css do %> - <%#= javascript_include_tag "ad_banner" #this line wont work %> - -<% end %> - - -

    - <%= f.label :title, t('admin.title') %> - <%= f.text_field :title, :class => 'text' %> -

    -

    - <%= f.label :picture_position, t('admin.picture_position') %> - <%= f.text_field :picture_position, :class => 'text' %> -

    - -

    - <%= f.label :post_date, t('admin.post_date') %> - <%= f.date_select :post_date, :order => [:year, :month, :day], :use_month_numbers => true %> -

    - -

    - <%= f.label :unpost_date, t('admin.unpost_date') %> - <%= f.date_select :unpost_date, :order => [:year, :month, :day], :use_month_numbers => true,:prompt => { :day => t('form.date_unlimited'), :month => t('form.date_unlimited'), :year => t('form.date_unlimited') } %> -

    -

    - <%= f.label :context, t('admin.context') %> - <%= f.text_field :context, :class => 'text' %> - -

    -

    - <%= f.label :direct_to_after_click, t('admin.direct_to_after_click') %> - <%= f.check_box :direct_to_after_click %> -

    -

    - <%= f.label :ad_fx, t('admin.ad_fx') %> - <%= f.select :ad_fx ,AdBanner::FX_TYPES %> -

    -

    - <%#= f.label :ad_images, t('admin.ad_images') %> - - <%# @ad_banner.ad_images.each do |ad_image| %> - <%#= render :partial => 'ad_image_update', :object => ad_image, :locals => { :field_name => "ad_images", :f => f, :classes => "r_destroy, r_edit" } %> - <%# end %> - <%= render :partial => "ad_image_update", :collection => @ad_banner.ad_images,:as => :ad_image, %> -

      - <%= render :partial => 'new_add_banner_file', :object => @ad_banner.ad_images.build, :locals => { :field_name => "new_ad_images[]", :f => f, :classes => "r_destroy" } %> -

      - -

      - - - <%#= render :partial => 'new_design_file', :object => @design.themes.build, :locals => { :field_name => "themes", :f => f, :classes => "r_destroy" } %> -

      diff --git a/app/views/admin/ad_banners/_modal_ad_banner_form.html.erb b/app/views/admin/ad_banners/_modal_ad_banner_form.html.erb new file mode 100644 index 00000000..976d11a9 --- /dev/null +++ b/app/views/admin/ad_banners/_modal_ad_banner_form.html.erb @@ -0,0 +1,40 @@ + + + \ No newline at end of file diff --git a/app/views/admin/ad_images/edit.html.erb b/app/views/admin/ad_images/edit.html.erb new file mode 100644 index 00000000..5fbf198c --- /dev/null +++ b/app/views/admin/ad_images/edit.html.erb @@ -0,0 +1,8 @@ +<%= flash_messages %> + +<%= form_for @ad_image, :url => admin_ad_banner_ad_image_path, :html => { :class => 'form' } do |f| %> + + <%= render :partial => "form", :locals => { :f => f } %> + + +<% end %> diff --git a/app/views/admin/ad_images/new.html.erb b/app/views/admin/ad_images/new.html.erb new file mode 100644 index 00000000..99379faa --- /dev/null +++ b/app/views/admin/ad_images/new.html.erb @@ -0,0 +1,8 @@ +<%= flash_messages %> + +<%= form_for @ad_image, :url => create_ad_image_admin_ad_banners_path, :html => { :class => 'form' ,:multipart => true} do |f| %> + + <%= render :partial => "form", :locals => { :f => f } %> + + +<% end %> diff --git a/app/views/layouts/_side_bar.html.erb b/app/views/layouts/_side_bar.html.erb index e2f757db..130c208d 100644 --- a/app/views/layouts/_side_bar.html.erb +++ b/app/views/layouts/_side_bar.html.erb @@ -29,6 +29,14 @@ <%= link_to content_tag(:i, nil, :class => 'icons-window-block') + t('admin.design'), admin_designs_path %> <% end -%> +<%= content_tag :li, :class => active_for_controllers('ad_banners') do -%> + <%= link_to content_tag(:i, nil, :class => 'icons-link') + t('admin.ad_banner'), admin_ad_banners_path %> + <%= content_tag :li, link_to(t('admin.all_ad_banners'), admin_ad_banners_path), :class => active_for_action('ad_banners', 'index') %> + <%= content_tag :li, link_to(t('admin.new_ad_banner'), new_admin_ad_banner_path), :class => active_for_action('ad_banners', 'new') %> + <%= content_tag :li, link_to(t('admin.new_ad_image'), new_ad_image_admin_ad_banners_path), :class => active_for_action('ad_banners', 'new_image') %> + +<% end -%> + <%= content_tag :li, :class => active_for_controllers('web_links', 'tags', 'web_link_categorys') do -%> <%= link_to content_tag(:i, nil, :class => 'icons-link') + t('admin.link'), panel_web_resource_back_end_web_links_path %> <%= content_tag :ul, :class => ("nav nav-list " + visible_for_controllers('web_links', 'tags', 'web_link_categorys')) do -%> diff --git a/config/routes.rb b/config/routes.rb index 112d96e1..99860bb6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -24,7 +24,14 @@ Orbit::Application.routes.draw do end end - resources :ad_banners + + resources :ad_banners do + collection do + match 'new_ad_image' => 'ad_images#new',:as => :new_ad_image,:via => :get + match 'new_ad_image' => 'ad_images#create',:as => :create_ad_image,:via => :post + end + resources :ad_images ,:except => [:show,:index] + end resources :dashboards resources :designs do collection do diff --git a/lib/parsers/parser_common.rb b/lib/parsers/parser_common.rb index 96cbb4b9..091d21ae 100644 --- a/lib/parsers/parser_common.rb +++ b/lib/parsers/parser_common.rb @@ -54,14 +54,24 @@ module ParserCommon $(document).ready(function(){ $('#slideshow-#{ad_banner.title.dehumanize}').cycle({delay: -1000, fx: '#{ad_banner.ad_fx.nil?? 'fade': ad_banner.ad_fx}', timeoutFn: getTimeout }); }); " res << "
      " - ad_banner.ad_images.each do |ad_image| - res << "" + printable_ad_images = [] + ad_banner.ad_images.each do |ad_image| + if ad_image.display? + ad_image.weight.times do + printable_ad_images << ad_image + end end + end + printable_ad_images.shuffle! + printable_ad_images.each do |ad_image| #TODO Need Reflact + res << "" + end res << "
      " end fragment = Nokogiri::HTML::DocumentFragment.new(body, res)