').text(value.street).html() + ' st., bld. ' + $('
').text(value.building).html();
55 | $(element).html(html);
56 | },
57 |
58 | /**
59 | Gets value from element's html
60 |
61 | @method html2value(html)
62 | **/
63 | html2value: function(html) {
64 | /*
65 | you may write parsing method to get value by element's html
66 | e.g. "Moscow, st. Lenina, bld. 15" => {city: "Moscow", street: "Lenina", building: "15"}
67 | but for complex structures it's not recommended.
68 | Better set value directly via javascript, e.g.
69 | editable({
70 | value: {
71 | city: "Moscow",
72 | street: "Lenina",
73 | building: "15"
74 | }
75 | });
76 | */
77 | return null;
78 | },
79 |
80 | /**
81 | Converts value to string.
82 | It is used in internal comparing (not for sending to server).
83 |
84 | @method value2str(value)
85 | **/
86 | value2str: function(value) {
87 | var str = '';
88 | if(value) {
89 | for(var k in value) {
90 | str = str + k + ':' + value[k] + ';';
91 | }
92 | }
93 | return str;
94 | },
95 |
96 | /*
97 | Converts string to value. Used for reading value from 'data-value' attribute.
98 |
99 | @method str2value(str)
100 | */
101 | str2value: function(str) {
102 | /*
103 | this is mainly for parsing value defined in data-value attribute.
104 | If you will always set value by javascript, no need to overwrite it
105 | */
106 | return str;
107 | },
108 |
109 | /**
110 | Sets value of input.
111 |
112 | @method value2input(value)
113 | @param {mixed} value
114 | **/
115 | value2input: function(value) {
116 | if(!value) {
117 | return;
118 | }
119 | this.$input.filter('[name="city"]').val(value.city);
120 | this.$input.filter('[name="street"]').val(value.street);
121 | this.$input.filter('[name="building"]').val(value.building);
122 | },
123 |
124 | /**
125 | Returns value of input.
126 |
127 | @method input2value()
128 | **/
129 | input2value: function() {
130 | return {
131 | city: this.$input.filter('[name="city"]').val(),
132 | street: this.$input.filter('[name="street"]').val(),
133 | building: this.$input.filter('[name="building"]').val()
134 | };
135 | },
136 |
137 | /**
138 | Activates input: sets focus on the first field.
139 |
140 | @method activate()
141 | **/
142 | activate: function() {
143 | this.$input.filter('[name="city"]').focus();
144 | },
145 |
146 | /**
147 | Attaches handler to submit form in case of 'showbuttons=false' mode
148 |
149 | @method autosubmit()
150 | **/
151 | autosubmit: function() {
152 | this.$input.keydown(function (e) {
153 | if (e.which === 13) {
154 | $(this).closest('form').submit();
155 | }
156 | });
157 | }
158 | });
159 |
160 | Address.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
161 | tpl: '
'+
162 | '
'+
163 | '
',
164 |
165 | inputclass: ''
166 | });
167 |
168 | $.fn.editabletypes.address = Address;
169 |
170 | }(window.jQuery));
--------------------------------------------------------------------------------
/app/assets/stylesheets/bootstrap-editable.scss:
--------------------------------------------------------------------------------
1 | /*! X-editable - v1.5.1
2 | * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3 | * http://github.com/vitalets/x-editable
4 | * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
5 | .editableform {
6 | margin-bottom: 0; /* overwrites bootstrap margin */
7 | }
8 |
9 | .editableform .control-group {
10 | margin-bottom: 0; /* overwrites bootstrap margin */
11 | white-space: nowrap; /* prevent wrapping buttons on new line */
12 | line-height: 20px; /* overwriting bootstrap line-height. See #133 */
13 | }
14 |
15 | /*
16 | BS3 width:1005 for inputs breaks editable form in popup
17 | See: https://github.com/vitalets/x-editable/issues/393
18 | */
19 | .editableform .form-control {
20 | width: auto;
21 | }
22 |
23 | .editable-buttons {
24 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
25 | vertical-align: top;
26 | margin-left: 7px;
27 | /* inline-block emulation for IE7*/
28 | zoom: 1;
29 | *display: inline;
30 | }
31 |
32 | .editable-buttons.editable-buttons-bottom {
33 | display: block;
34 | margin-top: 7px;
35 | margin-left: 0;
36 | }
37 |
38 | .editable-input {
39 | vertical-align: top;
40 | display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
41 | width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
42 | white-space: normal; /* reset white-space decalred in parent*/
43 | /* display-inline emulation for IE7*/
44 | zoom: 1;
45 | *display: inline;
46 | }
47 |
48 | .editable-buttons .editable-cancel {
49 | margin-left: 7px;
50 | }
51 |
52 | /*for jquery-ui buttons need set height to look more pretty*/
53 | .editable-buttons button.ui-button-icon-only {
54 | height: 24px;
55 | width: 30px;
56 | }
57 |
58 | .editableform-loading {
59 | background: image-url("bootstrap-editable/loading.gif") center center no-repeat;
60 | height: 25px;
61 | width: auto;
62 | min-width: 25px;
63 | }
64 |
65 | .editable-inline .editableform-loading {
66 | background-position: left 5px;
67 | }
68 |
69 | .editable-error-block {
70 | max-width: 300px;
71 | margin: 5px 0 0 0;
72 | width: auto;
73 | white-space: normal;
74 | }
75 |
76 | /*add padding for jquery ui*/
77 | .editable-error-block.ui-state-error {
78 | padding: 3px;
79 | }
80 |
81 | .editable-error {
82 | color: red;
83 | }
84 |
85 | /* ---- For specific types ---- */
86 |
87 | .editableform .editable-date {
88 | padding: 0;
89 | margin: 0;
90 | float: left;
91 | }
92 |
93 | /* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
94 | .editable-inline .add-on .icon-th {
95 | margin-top: 3px;
96 | margin-left: 1px;
97 | }
98 |
99 |
100 | /* checklist vertical alignment */
101 | .editable-checklist label input[type="checkbox"],
102 | .editable-checklist label span {
103 | vertical-align: middle;
104 | margin: 0;
105 | }
106 |
107 | .editable-checklist label {
108 | white-space: nowrap;
109 | }
110 |
111 | /* set exact width of textarea to fit buttons toolbar */
112 | .editable-wysihtml5 {
113 | width: 566px;
114 | height: 250px;
115 | }
116 |
117 | /* clear button shown as link in date inputs */
118 | .editable-clear {
119 | clear: both;
120 | font-size: 0.9em;
121 | text-decoration: none;
122 | text-align: right;
123 | }
124 |
125 | /* IOS-style clear button for text inputs */
126 | .editable-clear-x {
127 | background: image-url("bootstrap-editable/clear.png") center center no-repeat;
128 | display: block;
129 | width: 13px;
130 | height: 13px;
131 | position: absolute;
132 | opacity: 0.6;
133 | z-index: 100;
134 |
135 | top: 50%;
136 | right: 6px;
137 | margin-top: -6px;
138 |
139 | }
140 |
141 | .editable-clear-x:hover {
142 | opacity: 1;
143 | }
144 |
145 | .editable-pre-wrapped {
146 | white-space: pre-wrap;
147 | }
148 | .editable-container.editable-popup {
149 | max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
150 | }
151 |
152 | .editable-container.popover {
153 | width: auto; /* without this rule popover does not stretch */
154 | }
155 |
156 | .editable-container.editable-inline {
157 | display: inline-block;
158 | vertical-align: middle;
159 | width: auto;
160 | /* inline-block emulation for IE7*/
161 | zoom: 1;
162 | *display: inline;
163 | }
164 |
165 | .editable-container.ui-widget {
166 | font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */
167 | z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
168 | }
169 | .editable-click,
170 | a.editable-click,
171 | a.editable-click:hover {
172 | text-decoration: none;
173 | border-bottom: dashed 1px #0088cc;
174 | }
175 |
176 | .editable-click.editable-disabled,
177 | a.editable-click.editable-disabled,
178 | a.editable-click.editable-disabled:hover {
179 | color: #585858;
180 | cursor: default;
181 | border-bottom: none;
182 | }
183 |
184 | .editable-empty, .editable-empty:hover, .editable-empty:focus{
185 | font-style: italic;
186 | color: #DD1144;
187 | /* border-bottom: none; */
188 | text-decoration: none;
189 | }
190 |
191 | .editable-unsaved {
192 | font-weight: bold;
193 | }
194 |
195 | .editable-unsaved:after {
196 | /* content: '*'*/
197 | }
198 |
199 | .editable-bg-transition {
200 | -webkit-transition: background-color 1400ms ease-out;
201 | -moz-transition: background-color 1400ms ease-out;
202 | -o-transition: background-color 1400ms ease-out;
203 | -ms-transition: background-color 1400ms ease-out;
204 | transition: background-color 1400ms ease-out;
205 | }
206 |
207 | /*see https://github.com/vitalets/x-editable/issues/139 */
208 | .form-horizontal .editable
209 | {
210 | padding-top: 5px;
211 | display:inline-block;
212 | }
213 |
214 | /* Removed datepicker css. If you want to use datepicker, add latest datepicker library such as bootstrap-datepicker. */
215 |
--------------------------------------------------------------------------------
/app/assets/javascripts/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.min.js:
--------------------------------------------------------------------------------
1 | !function($,wysi){"use strict";var tpl={"font-styles":function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"
"+""+" "+locale.font_styles.normal+" "+""+""+""},emphasis:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"
"+""+""},lists:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"
"+""+""},link:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"
"+""+""+""},image:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"
"+""+""+""},html:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"
"+""+""},color:function(locale,options){var size=options&&options.size?" btn-"+options.size:"";return"
"+""+""+locale.colours.black+" "+""+""+""}};var templates=function(key,locale,options){return tpl[key](locale,options)};var Wysihtml5=function(el,options){this.el=el;var toolbarOpts=options||defaultOptions;for(var t in toolbarOpts.customTemplates){tpl[t]=toolbarOpts.customTemplates[t]}this.toolbar=this.createToolbar(el,toolbarOpts);this.editor=this.createEditor(options);window.editor=this.editor;$("iframe.wysihtml5-sandbox").each(function(i,el){$(el.contentWindow).off("focus.wysihtml5").on({"focus.wysihtml5":function(){$("li.dropdown").removeClass("open")}})})};Wysihtml5.prototype={constructor:Wysihtml5,createEditor:function(options){options=options||{};options=$.extend(true,{},options);options.toolbar=this.toolbar[0];var editor=new wysi.Editor(this.el[0],options);if(options&&options.events){for(var eventName in options.events){editor.on(eventName,options.events[eventName])}}return editor},createToolbar:function(el,options){var self=this;var toolbar=$("
",{"class":"wysihtml5-toolbar",style:"display:none"});var culture=options.locale||defaultOptions.locale||"en";for(var key in defaultOptions){var value=false;if(options[key]!==undefined){if(options[key]===true){value=true}}else{value=defaultOptions[key]}if(value===true){toolbar.append(templates(key,locale[culture],options));if(key==="html"){this.initHtml(toolbar)}if(key==="link"){this.initInsertLink(toolbar)}if(key==="image"){this.initInsertImage(toolbar)}}}if(options.toolbar){for(key in options.toolbar){toolbar.append(options.toolbar[key])}}toolbar.find("a[data-wysihtml5-command='formatBlock']").click(function(e){var target=e.target||e.srcElement;var el=$(target);self.toolbar.find(".current-font").text(el.html())});toolbar.find("a[data-wysihtml5-command='foreColor']").click(function(e){var target=e.target||e.srcElement;var el=$(target);self.toolbar.find(".current-color").text(el.html())});this.el.before(toolbar);return toolbar},initHtml:function(toolbar){var changeViewSelector="a[data-wysihtml5-action='change_view']";toolbar.find(changeViewSelector).click(function(e){toolbar.find("a.btn").not(changeViewSelector).toggleClass("disabled")})},initInsertImage:function(toolbar){var self=this;var insertImageModal=toolbar.find(".bootstrap-wysihtml5-insert-image-modal");var urlInput=insertImageModal.find(".bootstrap-wysihtml5-insert-image-url");var insertButton=insertImageModal.find("a.btn-primary");var initialValue=urlInput.val();var caretBookmark;var insertImage=function(){var url=urlInput.val();urlInput.val(initialValue);self.editor.currentView.element.focus();if(caretBookmark){self.editor.composer.selection.setBookmark(caretBookmark);caretBookmark=null}self.editor.composer.commands.exec("insertImage",url)};urlInput.keypress(function(e){if(e.which==13){insertImage();insertImageModal.modal("hide")}});insertButton.click(insertImage);insertImageModal.on("shown",function(){urlInput.focus()});insertImageModal.on("hide",function(){self.editor.currentView.element.focus()});toolbar.find("a[data-wysihtml5-command=insertImage]").click(function(){var activeButton=$(this).hasClass("wysihtml5-command-active");if(!activeButton){self.editor.currentView.element.focus(false);caretBookmark=self.editor.composer.selection.getBookmark();insertImageModal.appendTo("body").modal("show");insertImageModal.on("click.dismiss.modal",'[data-dismiss="modal"]',function(e){e.stopPropagation()});return false}else{return true}})},initInsertLink:function(toolbar){var self=this;var insertLinkModal=toolbar.find(".bootstrap-wysihtml5-insert-link-modal");var urlInput=insertLinkModal.find(".bootstrap-wysihtml5-insert-link-url");var insertButton=insertLinkModal.find("a.btn-primary");var initialValue=urlInput.val();var caretBookmark;var insertLink=function(){var url=urlInput.val();urlInput.val(initialValue);self.editor.currentView.element.focus();if(caretBookmark){self.editor.composer.selection.setBookmark(caretBookmark);caretBookmark=null}self.editor.composer.commands.exec("createLink",{href:url,target:"_blank",rel:"nofollow"})};var pressedEnter=false;urlInput.keypress(function(e){if(e.which==13){insertLink();insertLinkModal.modal("hide")}});insertButton.click(insertLink);insertLinkModal.on("shown",function(){urlInput.focus()});insertLinkModal.on("hide",function(){self.editor.currentView.element.focus()});toolbar.find("a[data-wysihtml5-command=createLink]").click(function(){var activeButton=$(this).hasClass("wysihtml5-command-active");if(!activeButton){self.editor.currentView.element.focus(false);caretBookmark=self.editor.composer.selection.getBookmark();insertLinkModal.appendTo("body").modal("show");insertLinkModal.on("click.dismiss.modal",'[data-dismiss="modal"]',function(e){e.stopPropagation()});return false}else{return true}})}};var methods={resetDefaults:function(){$.fn.wysihtml5.defaultOptions=$.extend(true,{},$.fn.wysihtml5.defaultOptionsCache)},bypassDefaults:function(options){return this.each(function(){var $this=$(this);$this.data("wysihtml5",new Wysihtml5($this,options))})},shallowExtend:function(options){var settings=$.extend({},$.fn.wysihtml5.defaultOptions,options||{});var that=this;return methods.bypassDefaults.apply(that,[settings])},deepExtend:function(options){var settings=$.extend(true,{},$.fn.wysihtml5.defaultOptions,options||{});var that=this;return methods.bypassDefaults.apply(that,[settings])},init:function(options){var that=this;return methods.shallowExtend.apply(that,[options])}};$.fn.wysihtml5=function(method){if(methods[method]){return methods[method].apply(this,Array.prototype.slice.call(arguments,1))}else if(typeof method==="object"||!method){return methods.init.apply(this,arguments)}else{$.error("Method "+method+" does not exist on jQuery.wysihtml5")}};$.fn.wysihtml5.Constructor=Wysihtml5;var defaultOptions=$.fn.wysihtml5.defaultOptions={"font-styles":true,color:false,emphasis:true,lists:true,html:false,link:true,image:true,events:{},parserRules:{classes:{"wysiwyg-color-silver":1,"wysiwyg-color-gray":1,"wysiwyg-color-white":1,"wysiwyg-color-maroon":1,"wysiwyg-color-red":1,"wysiwyg-color-purple":1,"wysiwyg-color-fuchsia":1,"wysiwyg-color-green":1,"wysiwyg-color-lime":1,"wysiwyg-color-olive":1,"wysiwyg-color-yellow":1,"wysiwyg-color-navy":1,"wysiwyg-color-blue":1,"wysiwyg-color-teal":1,"wysiwyg-color-aqua":1,"wysiwyg-color-orange":1},tags:{b:{},i:{},br:{},ol:{},ul:{},li:{},h1:{},h2:{},h3:{},blockquote:{},u:1,img:{check_attributes:{width:"numbers",alt:"alt",src:"url",height:"numbers"}},a:{set_attributes:{target:"_blank",rel:"nofollow"},check_attributes:{href:"url"}},span:1,div:1,code:1,pre:1}},stylesheets:["./lib/css/wysiwyg-color.css"],locale:"en"};if(typeof $.fn.wysihtml5.defaultOptionsCache==="undefined"){$.fn.wysihtml5.defaultOptionsCache=$.extend(true,{},$.fn.wysihtml5.defaultOptions)}var locale=$.fn.wysihtml5.locale={en:{font_styles:{normal:"Normal text",h1:"Heading 1",h2:"Heading 2",h3:"Heading 3"},emphasis:{bold:"Bold",italic:"Italic",underline:"Underline"},lists:{unordered:"Unordered list",ordered:"Ordered list",outdent:"Outdent",indent:"Indent"},link:{insert:"Insert link",cancel:"Cancel"},image:{insert:"Insert image",cancel:"Cancel"},html:{edit:"Edit HTML"},colours:{black:"Black",silver:"Silver",gray:"Grey",maroon:"Maroon",red:"Red",purple:"Purple",green:"Green",olive:"Olive",navy:"Navy",blue:"Blue",orange:"Orange"}}}}(window.jQuery,window.wysihtml5);
--------------------------------------------------------------------------------
/app/assets/javascripts/inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.js:
--------------------------------------------------------------------------------
1 | !function($, wysi) {
2 | "use strict";
3 |
4 | var tpl = {
5 | "font-styles": function(locale, options) {
6 | var size = (options && options.size) ? ' btn-'+options.size : '';
7 | return "
" +
8 | "" +
9 | " " + locale.font_styles.normal + " " +
10 | "" +
11 | "" +
17 | "";
18 | },
19 |
20 | "emphasis": function(locale, options) {
21 | var size = (options && options.size) ? ' btn-'+options.size : '';
22 | return "
" +
23 | "" +
28 | "";
29 | },
30 |
31 | "lists": function(locale, options) {
32 | var size = (options && options.size) ? ' btn-'+options.size : '';
33 | return "
" +
34 | "" +
35 | "
" +
36 | "
" +
37 | "
" +
38 | "
" +
39 | "
" +
40 | "";
41 | },
42 |
43 | "link": function(locale, options) {
44 | var size = (options && options.size) ? ' btn-'+options.size : '';
45 | return "
" +
46 | "" +
47 | "" +
51 | "
" +
52 | "" +
53 | "
" +
54 | "" +
58 | "
" +
59 | "" +
60 | "";
61 | },
62 |
63 | "image": function(locale, options) {
64 | var size = (options && options.size) ? ' btn-'+options.size : '';
65 | return "
" +
66 | "" +
67 | "" +
71 | "
" +
72 | "" +
73 | "
" +
74 | "" +
78 | "
" +
79 | "" +
80 | "";
81 | },
82 |
83 | "html": function(locale, options) {
84 | var size = (options && options.size) ? ' btn-'+options.size : '';
85 | return "
" +
86 | "" +
89 | "";
90 | },
91 |
92 | "color": function(locale, options) {
93 | var size = (options && options.size) ? ' btn-'+options.size : '';
94 | return "
" +
95 | "" +
96 | "" + locale.colours.black + " " +
97 | "" +
98 | "" +
111 | "";
112 | }
113 | };
114 |
115 | var templates = function(key, locale, options) {
116 | return tpl[key](locale, options);
117 | };
118 |
119 |
120 | var Wysihtml5 = function(el, options) {
121 | this.el = el;
122 | var toolbarOpts = options || defaultOptions;
123 | for(var t in toolbarOpts.customTemplates) {
124 | tpl[t] = toolbarOpts.customTemplates[t];
125 | }
126 | this.toolbar = this.createToolbar(el, toolbarOpts);
127 | this.editor = this.createEditor(options);
128 |
129 | window.editor = this.editor;
130 |
131 | $('iframe.wysihtml5-sandbox').each(function(i, el){
132 | $(el.contentWindow).off('focus.wysihtml5').on({
133 | 'focus.wysihtml5' : function(){
134 | $('li.dropdown').removeClass('open');
135 | }
136 | });
137 | });
138 | };
139 |
140 | Wysihtml5.prototype = {
141 |
142 | constructor: Wysihtml5,
143 |
144 | createEditor: function(options) {
145 | options = options || {};
146 |
147 | // Add the toolbar to a clone of the options object so multiple instances
148 | // of the WYISYWG don't break because "toolbar" is already defined
149 | options = $.extend(true, {}, options);
150 | options.toolbar = this.toolbar[0];
151 |
152 | var editor = new wysi.Editor(this.el[0], options);
153 |
154 | if(options && options.events) {
155 | for(var eventName in options.events) {
156 | editor.on(eventName, options.events[eventName]);
157 | }
158 | }
159 | return editor;
160 | },
161 |
162 | createToolbar: function(el, options) {
163 | var self = this;
164 | var toolbar = $("
", {
165 | 'class' : "wysihtml5-toolbar",
166 | 'style': "display:none"
167 | });
168 | var culture = options.locale || defaultOptions.locale || "en";
169 | for(var key in defaultOptions) {
170 | var value = false;
171 |
172 | if(options[key] !== undefined) {
173 | if(options[key] === true) {
174 | value = true;
175 | }
176 | } else {
177 | value = defaultOptions[key];
178 | }
179 |
180 | if(value === true) {
181 | toolbar.append(templates(key, locale[culture], options));
182 |
183 | if(key === "html") {
184 | this.initHtml(toolbar);
185 | }
186 |
187 | if(key === "link") {
188 | this.initInsertLink(toolbar);
189 | }
190 |
191 | if(key === "image") {
192 | this.initInsertImage(toolbar);
193 | }
194 | }
195 | }
196 |
197 | if(options.toolbar) {
198 | for(key in options.toolbar) {
199 | toolbar.append(options.toolbar[key]);
200 | }
201 | }
202 |
203 | toolbar.find("a[data-wysihtml5-command='formatBlock']").click(function(e) {
204 | var target = e.target || e.srcElement;
205 | var el = $(target);
206 | self.toolbar.find('.current-font').text(el.html());
207 | });
208 |
209 | toolbar.find("a[data-wysihtml5-command='foreColor']").click(function(e) {
210 | var target = e.target || e.srcElement;
211 | var el = $(target);
212 | self.toolbar.find('.current-color').text(el.html());
213 | });
214 |
215 | this.el.before(toolbar);
216 |
217 | return toolbar;
218 | },
219 |
220 | initHtml: function(toolbar) {
221 | var changeViewSelector = "a[data-wysihtml5-action='change_view']";
222 | toolbar.find(changeViewSelector).click(function(e) {
223 | toolbar.find('a.btn').not(changeViewSelector).toggleClass('disabled');
224 | });
225 | },
226 |
227 | initInsertImage: function(toolbar) {
228 | var self = this;
229 | var insertImageModal = toolbar.find('.bootstrap-wysihtml5-insert-image-modal');
230 | var urlInput = insertImageModal.find('.bootstrap-wysihtml5-insert-image-url');
231 | var insertButton = insertImageModal.find('a.btn-primary');
232 | var initialValue = urlInput.val();
233 | var caretBookmark;
234 |
235 | var insertImage = function() {
236 | var url = urlInput.val();
237 | urlInput.val(initialValue);
238 | self.editor.currentView.element.focus();
239 | if (caretBookmark) {
240 | self.editor.composer.selection.setBookmark(caretBookmark);
241 | caretBookmark = null;
242 | }
243 | self.editor.composer.commands.exec("insertImage", url);
244 | };
245 |
246 | urlInput.keypress(function(e) {
247 | if(e.which == 13) {
248 | insertImage();
249 | insertImageModal.modal('hide');
250 | }
251 | });
252 |
253 | insertButton.click(insertImage);
254 |
255 | insertImageModal.on('shown', function() {
256 | urlInput.focus();
257 | });
258 |
259 | insertImageModal.on('hide', function() {
260 | self.editor.currentView.element.focus();
261 | });
262 |
263 | toolbar.find('a[data-wysihtml5-command=insertImage]').click(function() {
264 | var activeButton = $(this).hasClass("wysihtml5-command-active");
265 |
266 | if (!activeButton) {
267 | self.editor.currentView.element.focus(false);
268 | caretBookmark = self.editor.composer.selection.getBookmark();
269 | insertImageModal.appendTo('body').modal('show');
270 | insertImageModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function(e) {
271 | e.stopPropagation();
272 | });
273 | return false;
274 | }
275 | else {
276 | return true;
277 | }
278 | });
279 | },
280 |
281 | initInsertLink: function(toolbar) {
282 | var self = this;
283 | var insertLinkModal = toolbar.find('.bootstrap-wysihtml5-insert-link-modal');
284 | var urlInput = insertLinkModal.find('.bootstrap-wysihtml5-insert-link-url');
285 | var insertButton = insertLinkModal.find('a.btn-primary');
286 | var initialValue = urlInput.val();
287 | var caretBookmark;
288 |
289 | var insertLink = function() {
290 | var url = urlInput.val();
291 | urlInput.val(initialValue);
292 | self.editor.currentView.element.focus();
293 | if (caretBookmark) {
294 | self.editor.composer.selection.setBookmark(caretBookmark);
295 | caretBookmark = null;
296 | }
297 | self.editor.composer.commands.exec("createLink", {
298 | href: url,
299 | target: "_blank",
300 | rel: "nofollow"
301 | });
302 | };
303 | var pressedEnter = false;
304 |
305 | urlInput.keypress(function(e) {
306 | if(e.which == 13) {
307 | insertLink();
308 | insertLinkModal.modal('hide');
309 | }
310 | });
311 |
312 | insertButton.click(insertLink);
313 |
314 | insertLinkModal.on('shown', function() {
315 | urlInput.focus();
316 | });
317 |
318 | insertLinkModal.on('hide', function() {
319 | self.editor.currentView.element.focus();
320 | });
321 |
322 | toolbar.find('a[data-wysihtml5-command=createLink]').click(function() {
323 | var activeButton = $(this).hasClass("wysihtml5-command-active");
324 |
325 | if (!activeButton) {
326 | self.editor.currentView.element.focus(false);
327 | caretBookmark = self.editor.composer.selection.getBookmark();
328 | insertLinkModal.appendTo('body').modal('show');
329 | insertLinkModal.on('click.dismiss.modal', '[data-dismiss="modal"]', function(e) {
330 | e.stopPropagation();
331 | });
332 | return false;
333 | }
334 | else {
335 | return true;
336 | }
337 | });
338 | }
339 | };
340 |
341 | // these define our public api
342 | var methods = {
343 | resetDefaults: function() {
344 | $.fn.wysihtml5.defaultOptions = $.extend(true, {}, $.fn.wysihtml5.defaultOptionsCache);
345 | },
346 | bypassDefaults: function(options) {
347 | return this.each(function () {
348 | var $this = $(this);
349 | $this.data('wysihtml5', new Wysihtml5($this, options));
350 | });
351 | },
352 | shallowExtend: function (options) {
353 | var settings = $.extend({}, $.fn.wysihtml5.defaultOptions, options || {});
354 | var that = this;
355 | return methods.bypassDefaults.apply(that, [settings]);
356 | },
357 | deepExtend: function(options) {
358 | var settings = $.extend(true, {}, $.fn.wysihtml5.defaultOptions, options || {});
359 | var that = this;
360 | return methods.bypassDefaults.apply(that, [settings]);
361 | },
362 | init: function(options) {
363 | var that = this;
364 | return methods.shallowExtend.apply(that, [options]);
365 | }
366 | };
367 |
368 | $.fn.wysihtml5 = function ( method ) {
369 | if ( methods[method] ) {
370 | return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
371 | } else if ( typeof method === 'object' || ! method ) {
372 | return methods.init.apply( this, arguments );
373 | } else {
374 | $.error( 'Method ' + method + ' does not exist on jQuery.wysihtml5' );
375 | }
376 | };
377 |
378 | $.fn.wysihtml5.Constructor = Wysihtml5;
379 |
380 | var defaultOptions = $.fn.wysihtml5.defaultOptions = {
381 | "font-styles": true,
382 | "color": false,
383 | "emphasis": true,
384 | "lists": true,
385 | "html": false,
386 | "link": true,
387 | "image": true,
388 | events: {},
389 | parserRules: {
390 | classes: {
391 | // (path_to_project/lib/css/wysiwyg-color.css)
392 | "wysiwyg-color-silver" : 1,
393 | "wysiwyg-color-gray" : 1,
394 | "wysiwyg-color-white" : 1,
395 | "wysiwyg-color-maroon" : 1,
396 | "wysiwyg-color-red" : 1,
397 | "wysiwyg-color-purple" : 1,
398 | "wysiwyg-color-fuchsia" : 1,
399 | "wysiwyg-color-green" : 1,
400 | "wysiwyg-color-lime" : 1,
401 | "wysiwyg-color-olive" : 1,
402 | "wysiwyg-color-yellow" : 1,
403 | "wysiwyg-color-navy" : 1,
404 | "wysiwyg-color-blue" : 1,
405 | "wysiwyg-color-teal" : 1,
406 | "wysiwyg-color-aqua" : 1,
407 | "wysiwyg-color-orange" : 1
408 | },
409 | tags: {
410 | "b": {},
411 | "i": {},
412 | "br": {},
413 | "ol": {},
414 | "ul": {},
415 | "li": {},
416 | "h1": {},
417 | "h2": {},
418 | "h3": {},
419 | "blockquote": {},
420 | "u": 1,
421 | "img": {
422 | "check_attributes": {
423 | "width": "numbers",
424 | "alt": "alt",
425 | "src": "url",
426 | "height": "numbers"
427 | }
428 | },
429 | "a": {
430 | set_attributes: {
431 | target: "_blank",
432 | rel: "nofollow"
433 | },
434 | check_attributes: {
435 | href: "url" // important to avoid XSS
436 | }
437 | },
438 | "span": 1,
439 | "div": 1,
440 | // to allow save and edit files with code tag hacks
441 | "code": 1,
442 | "pre": 1
443 | }
444 | },
445 | stylesheets: ["./lib/css/wysiwyg-color.css"], // (path_to_project/lib/css/wysiwyg-color.css)
446 | locale: "en"
447 | };
448 |
449 | if (typeof $.fn.wysihtml5.defaultOptionsCache === 'undefined') {
450 | $.fn.wysihtml5.defaultOptionsCache = $.extend(true, {}, $.fn.wysihtml5.defaultOptions);
451 | }
452 |
453 | var locale = $.fn.wysihtml5.locale = {
454 | en: {
455 | font_styles: {
456 | normal: "Normal text",
457 | h1: "Heading 1",
458 | h2: "Heading 2",
459 | h3: "Heading 3"
460 | },
461 | emphasis: {
462 | bold: "Bold",
463 | italic: "Italic",
464 | underline: "Underline"
465 | },
466 | lists: {
467 | unordered: "Unordered list",
468 | ordered: "Ordered list",
469 | outdent: "Outdent",
470 | indent: "Indent"
471 | },
472 | link: {
473 | insert: "Insert link",
474 | cancel: "Cancel"
475 | },
476 | image: {
477 | insert: "Insert image",
478 | cancel: "Cancel"
479 | },
480 | html: {
481 | edit: "Edit HTML"
482 | },
483 | colours: {
484 | black: "Black",
485 | silver: "Silver",
486 | gray: "Grey",
487 | maroon: "Maroon",
488 | red: "Red",
489 | purple: "Purple",
490 | green: "Green",
491 | olive: "Olive",
492 | navy: "Navy",
493 | blue: "Blue",
494 | orange: "Orange"
495 | }
496 | }
497 | };
498 |
499 | }(window.jQuery, window.wysihtml5);
500 |
--------------------------------------------------------------------------------
/app/assets/javascripts/inputs-ext/typeaheadjs/lib/typeahead.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * typeahead.js 0.9.3
3 | * https://github.com/twitter/typeahead
4 | * Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT
5 | */
6 |
7 | (function($) {
8 | var VERSION = "0.9.3";
9 | var utils = {
10 | isMsie: function() {
11 | var match = /(msie) ([\w.]+)/i.exec(navigator.userAgent);
12 | return match ? parseInt(match[2], 10) : false;
13 | },
14 | isBlankString: function(str) {
15 | return !str || /^\s*$/.test(str);
16 | },
17 | escapeRegExChars: function(str) {
18 | return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
19 | },
20 | isString: function(obj) {
21 | return typeof obj === "string";
22 | },
23 | isNumber: function(obj) {
24 | return typeof obj === "number";
25 | },
26 | isArray: $.isArray,
27 | isFunction: $.isFunction,
28 | isObject: $.isPlainObject,
29 | isUndefined: function(obj) {
30 | return typeof obj === "undefined";
31 | },
32 | bind: $.proxy,
33 | bindAll: function(obj) {
34 | var val;
35 | for (var key in obj) {
36 | $.isFunction(val = obj[key]) && (obj[key] = $.proxy(val, obj));
37 | }
38 | },
39 | indexOf: function(haystack, needle) {
40 | for (var i = 0; i < haystack.length; i++) {
41 | if (haystack[i] === needle) {
42 | return i;
43 | }
44 | }
45 | return -1;
46 | },
47 | each: $.each,
48 | map: $.map,
49 | filter: $.grep,
50 | every: function(obj, test) {
51 | var result = true;
52 | if (!obj) {
53 | return result;
54 | }
55 | $.each(obj, function(key, val) {
56 | if (!(result = test.call(null, val, key, obj))) {
57 | return false;
58 | }
59 | });
60 | return !!result;
61 | },
62 | some: function(obj, test) {
63 | var result = false;
64 | if (!obj) {
65 | return result;
66 | }
67 | $.each(obj, function(key, val) {
68 | if (result = test.call(null, val, key, obj)) {
69 | return false;
70 | }
71 | });
72 | return !!result;
73 | },
74 | mixin: $.extend,
75 | getUniqueId: function() {
76 | var counter = 0;
77 | return function() {
78 | return counter++;
79 | };
80 | }(),
81 | defer: function(fn) {
82 | setTimeout(fn, 0);
83 | },
84 | debounce: function(func, wait, immediate) {
85 | var timeout, result;
86 | return function() {
87 | var context = this, args = arguments, later, callNow;
88 | later = function() {
89 | timeout = null;
90 | if (!immediate) {
91 | result = func.apply(context, args);
92 | }
93 | };
94 | callNow = immediate && !timeout;
95 | clearTimeout(timeout);
96 | timeout = setTimeout(later, wait);
97 | if (callNow) {
98 | result = func.apply(context, args);
99 | }
100 | return result;
101 | };
102 | },
103 | throttle: function(func, wait) {
104 | var context, args, timeout, result, previous, later;
105 | previous = 0;
106 | later = function() {
107 | previous = new Date();
108 | timeout = null;
109 | result = func.apply(context, args);
110 | };
111 | return function() {
112 | var now = new Date(), remaining = wait - (now - previous);
113 | context = this;
114 | args = arguments;
115 | if (remaining <= 0) {
116 | clearTimeout(timeout);
117 | timeout = null;
118 | previous = now;
119 | result = func.apply(context, args);
120 | } else if (!timeout) {
121 | timeout = setTimeout(later, remaining);
122 | }
123 | return result;
124 | };
125 | },
126 | tokenizeQuery: function(str) {
127 | return $.trim(str).toLowerCase().split(/[\s]+/);
128 | },
129 | tokenizeText: function(str) {
130 | return $.trim(str).toLowerCase().split(/[\s\-_]+/);
131 | },
132 | getProtocol: function() {
133 | return location.protocol;
134 | },
135 | noop: function() {}
136 | };
137 | var EventTarget = function() {
138 | var eventSplitter = /\s+/;
139 | return {
140 | on: function(events, callback) {
141 | var event;
142 | if (!callback) {
143 | return this;
144 | }
145 | this._callbacks = this._callbacks || {};
146 | events = events.split(eventSplitter);
147 | while (event = events.shift()) {
148 | this._callbacks[event] = this._callbacks[event] || [];
149 | this._callbacks[event].push(callback);
150 | }
151 | return this;
152 | },
153 | trigger: function(events, data) {
154 | var event, callbacks;
155 | if (!this._callbacks) {
156 | return this;
157 | }
158 | events = events.split(eventSplitter);
159 | while (event = events.shift()) {
160 | if (callbacks = this._callbacks[event]) {
161 | for (var i = 0; i < callbacks.length; i += 1) {
162 | callbacks[i].call(this, {
163 | type: event,
164 | data: data
165 | });
166 | }
167 | }
168 | }
169 | return this;
170 | }
171 | };
172 | }();
173 | var EventBus = function() {
174 | var namespace = "typeahead:";
175 | function EventBus(o) {
176 | if (!o || !o.el) {
177 | $.error("EventBus initialized without el");
178 | }
179 | this.$el = $(o.el);
180 | }
181 | utils.mixin(EventBus.prototype, {
182 | trigger: function(type) {
183 | var args = [].slice.call(arguments, 1);
184 | this.$el.trigger(namespace + type, args);
185 | }
186 | });
187 | return EventBus;
188 | }();
189 | var PersistentStorage = function() {
190 | var ls, methods;
191 | try {
192 | ls = window.localStorage;
193 | ls.setItem("~~~", "!");
194 | ls.removeItem("~~~");
195 | } catch (err) {
196 | ls = null;
197 | }
198 | function PersistentStorage(namespace) {
199 | this.prefix = [ "__", namespace, "__" ].join("");
200 | this.ttlKey = "__ttl__";
201 | this.keyMatcher = new RegExp("^" + this.prefix);
202 | }
203 | if (ls && window.JSON) {
204 | methods = {
205 | _prefix: function(key) {
206 | return this.prefix + key;
207 | },
208 | _ttlKey: function(key) {
209 | return this._prefix(key) + this.ttlKey;
210 | },
211 | get: function(key) {
212 | if (this.isExpired(key)) {
213 | this.remove(key);
214 | }
215 | return decode(ls.getItem(this._prefix(key)));
216 | },
217 | set: function(key, val, ttl) {
218 | if (utils.isNumber(ttl)) {
219 | ls.setItem(this._ttlKey(key), encode(now() + ttl));
220 | } else {
221 | ls.removeItem(this._ttlKey(key));
222 | }
223 | return ls.setItem(this._prefix(key), encode(val));
224 | },
225 | remove: function(key) {
226 | ls.removeItem(this._ttlKey(key));
227 | ls.removeItem(this._prefix(key));
228 | return this;
229 | },
230 | clear: function() {
231 | var i, key, keys = [], len = ls.length;
232 | for (i = 0; i < len; i++) {
233 | if ((key = ls.key(i)).match(this.keyMatcher)) {
234 | keys.push(key.replace(this.keyMatcher, ""));
235 | }
236 | }
237 | for (i = keys.length; i--; ) {
238 | this.remove(keys[i]);
239 | }
240 | return this;
241 | },
242 | isExpired: function(key) {
243 | var ttl = decode(ls.getItem(this._ttlKey(key)));
244 | return utils.isNumber(ttl) && now() > ttl ? true : false;
245 | }
246 | };
247 | } else {
248 | methods = {
249 | get: utils.noop,
250 | set: utils.noop,
251 | remove: utils.noop,
252 | clear: utils.noop,
253 | isExpired: utils.noop
254 | };
255 | }
256 | utils.mixin(PersistentStorage.prototype, methods);
257 | return PersistentStorage;
258 | function now() {
259 | return new Date().getTime();
260 | }
261 | function encode(val) {
262 | return JSON.stringify(utils.isUndefined(val) ? null : val);
263 | }
264 | function decode(val) {
265 | return JSON.parse(val);
266 | }
267 | }();
268 | var RequestCache = function() {
269 | function RequestCache(o) {
270 | utils.bindAll(this);
271 | o = o || {};
272 | this.sizeLimit = o.sizeLimit || 10;
273 | this.cache = {};
274 | this.cachedKeysByAge = [];
275 | }
276 | utils.mixin(RequestCache.prototype, {
277 | get: function(url) {
278 | return this.cache[url];
279 | },
280 | set: function(url, resp) {
281 | var requestToEvict;
282 | if (this.cachedKeysByAge.length === this.sizeLimit) {
283 | requestToEvict = this.cachedKeysByAge.shift();
284 | delete this.cache[requestToEvict];
285 | }
286 | this.cache[url] = resp;
287 | this.cachedKeysByAge.push(url);
288 | }
289 | });
290 | return RequestCache;
291 | }();
292 | var Transport = function() {
293 | var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests, requestCache;
294 | function Transport(o) {
295 | utils.bindAll(this);
296 | o = utils.isString(o) ? {
297 | url: o
298 | } : o;
299 | requestCache = requestCache || new RequestCache();
300 | maxPendingRequests = utils.isNumber(o.maxParallelRequests) ? o.maxParallelRequests : maxPendingRequests || 6;
301 | this.url = o.url;
302 | this.wildcard = o.wildcard || "%QUERY";
303 | this.filter = o.filter;
304 | this.replace = o.replace;
305 | this.ajaxSettings = {
306 | type: "get",
307 | cache: o.cache,
308 | timeout: o.timeout,
309 | dataType: o.dataType || "json",
310 | beforeSend: o.beforeSend
311 | };
312 | this._get = (/^throttle$/i.test(o.rateLimitFn) ? utils.throttle : utils.debounce)(this._get, o.rateLimitWait || 300);
313 | }
314 | utils.mixin(Transport.prototype, {
315 | _get: function(url, cb) {
316 | var that = this;
317 | if (belowPendingRequestsThreshold()) {
318 | this._sendRequest(url).done(done);
319 | } else {
320 | this.onDeckRequestArgs = [].slice.call(arguments, 0);
321 | }
322 | function done(resp) {
323 | var data = that.filter ? that.filter(resp) : resp;
324 | cb && cb(data);
325 | requestCache.set(url, resp);
326 | }
327 | },
328 | _sendRequest: function(url) {
329 | var that = this, jqXhr = pendingRequests[url];
330 | if (!jqXhr) {
331 | incrementPendingRequests();
332 | jqXhr = pendingRequests[url] = $.ajax(url, this.ajaxSettings).always(always);
333 | }
334 | return jqXhr;
335 | function always() {
336 | decrementPendingRequests();
337 | pendingRequests[url] = null;
338 | if (that.onDeckRequestArgs) {
339 | that._get.apply(that, that.onDeckRequestArgs);
340 | that.onDeckRequestArgs = null;
341 | }
342 | }
343 | },
344 | get: function(query, cb) {
345 | var that = this, encodedQuery = encodeURIComponent(query || ""), url, resp;
346 | cb = cb || utils.noop;
347 | url = this.replace ? this.replace(this.url, encodedQuery) : this.url.replace(this.wildcard, encodedQuery);
348 | if (resp = requestCache.get(url)) {
349 | utils.defer(function() {
350 | cb(that.filter ? that.filter(resp) : resp);
351 | });
352 | } else {
353 | this._get(url, cb);
354 | }
355 | return !!resp;
356 | }
357 | });
358 | return Transport;
359 | function incrementPendingRequests() {
360 | pendingRequestsCount++;
361 | }
362 | function decrementPendingRequests() {
363 | pendingRequestsCount--;
364 | }
365 | function belowPendingRequestsThreshold() {
366 | return pendingRequestsCount < maxPendingRequests;
367 | }
368 | }();
369 | var Dataset = function() {
370 | var keys = {
371 | thumbprint: "thumbprint",
372 | protocol: "protocol",
373 | itemHash: "itemHash",
374 | adjacencyList: "adjacencyList"
375 | };
376 | function Dataset(o) {
377 | utils.bindAll(this);
378 | if (utils.isString(o.template) && !o.engine) {
379 | $.error("no template engine specified");
380 | }
381 | if (!o.local && !o.prefetch && !o.remote) {
382 | $.error("one of local, prefetch, or remote is required");
383 | }
384 | this.name = o.name || utils.getUniqueId();
385 | this.limit = o.limit || 5;
386 | this.minLength = o.minLength || 1;
387 | this.header = o.header;
388 | this.footer = o.footer;
389 | this.valueKey = o.valueKey || "value";
390 | this.template = compileTemplate(o.template, o.engine, this.valueKey);
391 | this.local = o.local;
392 | this.prefetch = o.prefetch;
393 | this.remote = o.remote;
394 | this.itemHash = {};
395 | this.adjacencyList = {};
396 | this.storage = o.name ? new PersistentStorage(o.name) : null;
397 | }
398 | utils.mixin(Dataset.prototype, {
399 | _processLocalData: function(data) {
400 | this._mergeProcessedData(this._processData(data));
401 | },
402 | _loadPrefetchData: function(o) {
403 | var that = this, thumbprint = VERSION + (o.thumbprint || ""), storedThumbprint, storedProtocol, storedItemHash, storedAdjacencyList, isExpired, deferred;
404 | if (this.storage) {
405 | storedThumbprint = this.storage.get(keys.thumbprint);
406 | storedProtocol = this.storage.get(keys.protocol);
407 | storedItemHash = this.storage.get(keys.itemHash);
408 | storedAdjacencyList = this.storage.get(keys.adjacencyList);
409 | }
410 | isExpired = storedThumbprint !== thumbprint || storedProtocol !== utils.getProtocol();
411 | o = utils.isString(o) ? {
412 | url: o
413 | } : o;
414 | o.ttl = utils.isNumber(o.ttl) ? o.ttl : 24 * 60 * 60 * 1e3;
415 | if (storedItemHash && storedAdjacencyList && !isExpired) {
416 | this._mergeProcessedData({
417 | itemHash: storedItemHash,
418 | adjacencyList: storedAdjacencyList
419 | });
420 | deferred = $.Deferred().resolve();
421 | } else {
422 | deferred = $.getJSON(o.url).done(processPrefetchData);
423 | }
424 | return deferred;
425 | function processPrefetchData(data) {
426 | var filteredData = o.filter ? o.filter(data) : data, processedData = that._processData(filteredData), itemHash = processedData.itemHash, adjacencyList = processedData.adjacencyList;
427 | if (that.storage) {
428 | that.storage.set(keys.itemHash, itemHash, o.ttl);
429 | that.storage.set(keys.adjacencyList, adjacencyList, o.ttl);
430 | that.storage.set(keys.thumbprint, thumbprint, o.ttl);
431 | that.storage.set(keys.protocol, utils.getProtocol(), o.ttl);
432 | }
433 | that._mergeProcessedData(processedData);
434 | }
435 | },
436 | _transformDatum: function(datum) {
437 | var value = utils.isString(datum) ? datum : datum[this.valueKey], tokens = datum.tokens || utils.tokenizeText(value), item = {
438 | value: value,
439 | tokens: tokens
440 | };
441 | if (utils.isString(datum)) {
442 | item.datum = {};
443 | item.datum[this.valueKey] = datum;
444 | } else {
445 | item.datum = datum;
446 | }
447 | item.tokens = utils.filter(item.tokens, function(token) {
448 | return !utils.isBlankString(token);
449 | });
450 | item.tokens = utils.map(item.tokens, function(token) {
451 | return token.toLowerCase();
452 | });
453 | return item;
454 | },
455 | _processData: function(data) {
456 | var that = this, itemHash = {}, adjacencyList = {};
457 | utils.each(data, function(i, datum) {
458 | var item = that._transformDatum(datum), id = utils.getUniqueId(item.value);
459 | itemHash[id] = item;
460 | utils.each(item.tokens, function(i, token) {
461 | var character = token.charAt(0), adjacency = adjacencyList[character] || (adjacencyList[character] = [ id ]);
462 | !~utils.indexOf(adjacency, id) && adjacency.push(id);
463 | });
464 | });
465 | return {
466 | itemHash: itemHash,
467 | adjacencyList: adjacencyList
468 | };
469 | },
470 | _mergeProcessedData: function(processedData) {
471 | var that = this;
472 | utils.mixin(this.itemHash, processedData.itemHash);
473 | utils.each(processedData.adjacencyList, function(character, adjacency) {
474 | var masterAdjacency = that.adjacencyList[character];
475 | that.adjacencyList[character] = masterAdjacency ? masterAdjacency.concat(adjacency) : adjacency;
476 | });
477 | },
478 | _getLocalSuggestions: function(terms) {
479 | var that = this, firstChars = [], lists = [], shortestList, suggestions = [];
480 | utils.each(terms, function(i, term) {
481 | var firstChar = term.charAt(0);
482 | !~utils.indexOf(firstChars, firstChar) && firstChars.push(firstChar);
483 | });
484 | utils.each(firstChars, function(i, firstChar) {
485 | var list = that.adjacencyList[firstChar];
486 | if (!list) {
487 | return false;
488 | }
489 | lists.push(list);
490 | if (!shortestList || list.length < shortestList.length) {
491 | shortestList = list;
492 | }
493 | });
494 | if (lists.length < firstChars.length) {
495 | return [];
496 | }
497 | utils.each(shortestList, function(i, id) {
498 | var item = that.itemHash[id], isCandidate, isMatch;
499 | isCandidate = utils.every(lists, function(list) {
500 | return ~utils.indexOf(list, id);
501 | });
502 | isMatch = isCandidate && utils.every(terms, function(term) {
503 | return utils.some(item.tokens, function(token) {
504 | return token.indexOf(term) === 0;
505 | });
506 | });
507 | isMatch && suggestions.push(item);
508 | });
509 | return suggestions;
510 | },
511 | initialize: function() {
512 | var deferred;
513 | this.local && this._processLocalData(this.local);
514 | this.transport = this.remote ? new Transport(this.remote) : null;
515 | deferred = this.prefetch ? this._loadPrefetchData(this.prefetch) : $.Deferred().resolve();
516 | this.local = this.prefetch = this.remote = null;
517 | this.initialize = function() {
518 | return deferred;
519 | };
520 | return deferred;
521 | },
522 | getSuggestions: function(query, cb) {
523 | var that = this, terms, suggestions, cacheHit = false;
524 | if (query.length < this.minLength) {
525 | return;
526 | }
527 | terms = utils.tokenizeQuery(query);
528 | suggestions = this._getLocalSuggestions(terms).slice(0, this.limit);
529 | if (suggestions.length < this.limit && this.transport) {
530 | cacheHit = this.transport.get(query, processRemoteData);
531 | }
532 | !cacheHit && cb && cb(suggestions);
533 | function processRemoteData(data) {
534 | suggestions = suggestions.slice(0);
535 | utils.each(data, function(i, datum) {
536 | var item = that._transformDatum(datum), isDuplicate;
537 | isDuplicate = utils.some(suggestions, function(suggestion) {
538 | return item.value === suggestion.value;
539 | });
540 | !isDuplicate && suggestions.push(item);
541 | return suggestions.length < that.limit;
542 | });
543 | cb && cb(suggestions);
544 | }
545 | }
546 | });
547 | return Dataset;
548 | function compileTemplate(template, engine, valueKey) {
549 | var renderFn, compiledTemplate;
550 | if (utils.isFunction(template)) {
551 | renderFn = template;
552 | } else if (utils.isString(template)) {
553 | compiledTemplate = engine.compile(template);
554 | renderFn = utils.bind(compiledTemplate.render, compiledTemplate);
555 | } else {
556 | renderFn = function(context) {
557 | return "
" + context[valueKey] + "
";
558 | };
559 | }
560 | return renderFn;
561 | }
562 | }();
563 | var InputView = function() {
564 | function InputView(o) {
565 | var that = this;
566 | utils.bindAll(this);
567 | this.specialKeyCodeMap = {
568 | 9: "tab",
569 | 27: "esc",
570 | 37: "left",
571 | 39: "right",
572 | 13: "enter",
573 | 38: "up",
574 | 40: "down"
575 | };
576 | this.$hint = $(o.hint);
577 | this.$input = $(o.input).on("blur.tt", this._handleBlur).on("focus.tt", this._handleFocus).on("keydown.tt", this._handleSpecialKeyEvent);
578 | if (!utils.isMsie()) {
579 | this.$input.on("input.tt", this._compareQueryToInputValue);
580 | } else {
581 | this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
582 | if (that.specialKeyCodeMap[$e.which || $e.keyCode]) {
583 | return;
584 | }
585 | utils.defer(that._compareQueryToInputValue);
586 | });
587 | }
588 | this.query = this.$input.val();
589 | this.$overflowHelper = buildOverflowHelper(this.$input);
590 | }
591 | utils.mixin(InputView.prototype, EventTarget, {
592 | _handleFocus: function() {
593 | this.trigger("focused");
594 | },
595 | _handleBlur: function() {
596 | this.trigger("blured");
597 | },
598 | _handleSpecialKeyEvent: function($e) {
599 | var keyName = this.specialKeyCodeMap[$e.which || $e.keyCode];
600 | keyName && this.trigger(keyName + "Keyed", $e);
601 | },
602 | _compareQueryToInputValue: function() {
603 | var inputValue = this.getInputValue(), isSameQuery = compareQueries(this.query, inputValue), isSameQueryExceptWhitespace = isSameQuery ? this.query.length !== inputValue.length : false;
604 | if (isSameQueryExceptWhitespace) {
605 | this.trigger("whitespaceChanged", {
606 | value: this.query
607 | });
608 | } else if (!isSameQuery) {
609 | this.trigger("queryChanged", {
610 | value: this.query = inputValue
611 | });
612 | }
613 | },
614 | destroy: function() {
615 | this.$hint.off(".tt");
616 | this.$input.off(".tt");
617 | this.$hint = this.$input = this.$overflowHelper = null;
618 | },
619 | focus: function() {
620 | this.$input.focus();
621 | },
622 | blur: function() {
623 | this.$input.blur();
624 | },
625 | getQuery: function() {
626 | return this.query;
627 | },
628 | setQuery: function(query) {
629 | this.query = query;
630 | },
631 | getInputValue: function() {
632 | return this.$input.val();
633 | },
634 | setInputValue: function(value, silent) {
635 | this.$input.val(value);
636 | !silent && this._compareQueryToInputValue();
637 | },
638 | getHintValue: function() {
639 | return this.$hint.val();
640 | },
641 | setHintValue: function(value) {
642 | this.$hint.val(value);
643 | },
644 | getLanguageDirection: function() {
645 | return (this.$input.css("direction") || "ltr").toLowerCase();
646 | },
647 | isOverflow: function() {
648 | this.$overflowHelper.text(this.getInputValue());
649 | return this.$overflowHelper.width() > this.$input.width();
650 | },
651 | isCursorAtEnd: function() {
652 | var valueLength = this.$input.val().length, selectionStart = this.$input[0].selectionStart, range;
653 | if (utils.isNumber(selectionStart)) {
654 | return selectionStart === valueLength;
655 | } else if (document.selection) {
656 | range = document.selection.createRange();
657 | range.moveStart("character", -valueLength);
658 | return valueLength === range.text.length;
659 | }
660 | return true;
661 | }
662 | });
663 | return InputView;
664 | function buildOverflowHelper($input) {
665 | return $("
").css({
666 | position: "absolute",
667 | left: "-9999px",
668 | visibility: "hidden",
669 | whiteSpace: "nowrap",
670 | fontFamily: $input.css("font-family"),
671 | fontSize: $input.css("font-size"),
672 | fontStyle: $input.css("font-style"),
673 | fontVariant: $input.css("font-variant"),
674 | fontWeight: $input.css("font-weight"),
675 | wordSpacing: $input.css("word-spacing"),
676 | letterSpacing: $input.css("letter-spacing"),
677 | textIndent: $input.css("text-indent"),
678 | textRendering: $input.css("text-rendering"),
679 | textTransform: $input.css("text-transform")
680 | }).insertAfter($input);
681 | }
682 | function compareQueries(a, b) {
683 | a = (a || "").replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
684 | b = (b || "").replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
685 | return a === b;
686 | }
687 | }();
688 | var DropdownView = function() {
689 | var html = {
690 | suggestionsList: '
'
691 | }, css = {
692 | suggestionsList: {
693 | display: "block"
694 | },
695 | suggestion: {
696 | whiteSpace: "nowrap",
697 | cursor: "pointer"
698 | },
699 | suggestionChild: {
700 | whiteSpace: "normal"
701 | }
702 | };
703 | function DropdownView(o) {
704 | utils.bindAll(this);
705 | this.isOpen = false;
706 | this.isEmpty = true;
707 | this.isMouseOverDropdown = false;
708 | this.$menu = $(o.menu).on("mouseenter.tt", this._handleMouseenter).on("mouseleave.tt", this._handleMouseleave).on("click.tt", ".tt-suggestion", this._handleSelection).on("mouseover.tt", ".tt-suggestion", this._handleMouseover);
709 | }
710 | utils.mixin(DropdownView.prototype, EventTarget, {
711 | _handleMouseenter: function() {
712 | this.isMouseOverDropdown = true;
713 | },
714 | _handleMouseleave: function() {
715 | this.isMouseOverDropdown = false;
716 | },
717 | _handleMouseover: function($e) {
718 | var $suggestion = $($e.currentTarget);
719 | this._getSuggestions().removeClass("tt-is-under-cursor");
720 | $suggestion.addClass("tt-is-under-cursor");
721 | },
722 | _handleSelection: function($e) {
723 | var $suggestion = $($e.currentTarget);
724 | this.trigger("suggestionSelected", extractSuggestion($suggestion));
725 | },
726 | _show: function() {
727 | this.$menu.css("display", "block");
728 | },
729 | _hide: function() {
730 | this.$menu.hide();
731 | },
732 | _moveCursor: function(increment) {
733 | var $suggestions, $cur, nextIndex, $underCursor;
734 | if (!this.isVisible()) {
735 | return;
736 | }
737 | $suggestions = this._getSuggestions();
738 | $cur = $suggestions.filter(".tt-is-under-cursor");
739 | $cur.removeClass("tt-is-under-cursor");
740 | nextIndex = $suggestions.index($cur) + increment;
741 | nextIndex = (nextIndex + 1) % ($suggestions.length + 1) - 1;
742 | if (nextIndex === -1) {
743 | this.trigger("cursorRemoved");
744 | return;
745 | } else if (nextIndex < -1) {
746 | nextIndex = $suggestions.length - 1;
747 | }
748 | $underCursor = $suggestions.eq(nextIndex).addClass("tt-is-under-cursor");
749 | this._ensureVisibility($underCursor);
750 | this.trigger("cursorMoved", extractSuggestion($underCursor));
751 | },
752 | _getSuggestions: function() {
753 | return this.$menu.find(".tt-suggestions > .tt-suggestion");
754 | },
755 | _ensureVisibility: function($el) {
756 | var menuHeight = this.$menu.height() + parseInt(this.$menu.css("paddingTop"), 10) + parseInt(this.$menu.css("paddingBottom"), 10), menuScrollTop = this.$menu.scrollTop(), elTop = $el.position().top, elBottom = elTop + $el.outerHeight(true);
757 | if (elTop < 0) {
758 | this.$menu.scrollTop(menuScrollTop + elTop);
759 | } else if (menuHeight < elBottom) {
760 | this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));
761 | }
762 | },
763 | destroy: function() {
764 | this.$menu.off(".tt");
765 | this.$menu = null;
766 | },
767 | isVisible: function() {
768 | return this.isOpen && !this.isEmpty;
769 | },
770 | closeUnlessMouseIsOverDropdown: function() {
771 | if (!this.isMouseOverDropdown) {
772 | this.close();
773 | }
774 | },
775 | close: function() {
776 | if (this.isOpen) {
777 | this.isOpen = false;
778 | this.isMouseOverDropdown = false;
779 | this._hide();
780 | this.$menu.find(".tt-suggestions > .tt-suggestion").removeClass("tt-is-under-cursor");
781 | this.trigger("closed");
782 | }
783 | },
784 | open: function() {
785 | if (!this.isOpen) {
786 | this.isOpen = true;
787 | !this.isEmpty && this._show();
788 | this.trigger("opened");
789 | }
790 | },
791 | setLanguageDirection: function(dir) {
792 | var ltrCss = {
793 | left: "0",
794 | right: "auto"
795 | }, rtlCss = {
796 | left: "auto",
797 | right: " 0"
798 | };
799 | dir === "ltr" ? this.$menu.css(ltrCss) : this.$menu.css(rtlCss);
800 | },
801 | moveCursorUp: function() {
802 | this._moveCursor(-1);
803 | },
804 | moveCursorDown: function() {
805 | this._moveCursor(+1);
806 | },
807 | getSuggestionUnderCursor: function() {
808 | var $suggestion = this._getSuggestions().filter(".tt-is-under-cursor").first();
809 | return $suggestion.length > 0 ? extractSuggestion($suggestion) : null;
810 | },
811 | getFirstSuggestion: function() {
812 | var $suggestion = this._getSuggestions().first();
813 | return $suggestion.length > 0 ? extractSuggestion($suggestion) : null;
814 | },
815 | renderSuggestions: function(dataset, suggestions) {
816 | var datasetClassName = "tt-dataset-" + dataset.name, wrapper = '
%body
', compiledHtml, $suggestionsList, $dataset = this.$menu.find("." + datasetClassName), elBuilder, fragment, $el;
817 | if ($dataset.length === 0) {
818 | $suggestionsList = $(html.suggestionsList).css(css.suggestionsList);
819 | $dataset = $("
").addClass(datasetClassName).append(dataset.header).append($suggestionsList).append(dataset.footer).appendTo(this.$menu);
820 | }
821 | if (suggestions.length > 0) {
822 | this.isEmpty = false;
823 | this.isOpen && this._show();
824 | elBuilder = document.createElement("div");
825 | fragment = document.createDocumentFragment();
826 | utils.each(suggestions, function(i, suggestion) {
827 | suggestion.dataset = dataset.name;
828 | compiledHtml = dataset.template(suggestion.datum);
829 | elBuilder.innerHTML = wrapper.replace("%body", compiledHtml);
830 | $el = $(elBuilder.firstChild).css(css.suggestion).data("suggestion", suggestion);
831 | $el.children().each(function() {
832 | $(this).css(css.suggestionChild);
833 | });
834 | fragment.appendChild($el[0]);
835 | });
836 | $dataset.show().find(".tt-suggestions").html(fragment);
837 | } else {
838 | this.clearSuggestions(dataset.name);
839 | }
840 | this.trigger("suggestionsRendered");
841 | },
842 | clearSuggestions: function(datasetName) {
843 | var $datasets = datasetName ? this.$menu.find(".tt-dataset-" + datasetName) : this.$menu.find('[class^="tt-dataset-"]'), $suggestions = $datasets.find(".tt-suggestions");
844 | $datasets.hide();
845 | $suggestions.empty();
846 | if (this._getSuggestions().length === 0) {
847 | this.isEmpty = true;
848 | this._hide();
849 | }
850 | }
851 | });
852 | return DropdownView;
853 | function extractSuggestion($el) {
854 | return $el.data("suggestion");
855 | }
856 | }();
857 | var TypeaheadView = function() {
858 | var html = {
859 | wrapper: '',
860 | hint: '
',
861 | dropdown: ''
862 | }, css = {
863 | wrapper: {
864 | position: "relative",
865 | display: "inline-block"
866 | },
867 | hint: {
868 | position: "absolute",
869 | top: "0",
870 | left: "0",
871 | borderColor: "transparent",
872 | boxShadow: "none"
873 | },
874 | query: {
875 | position: "relative",
876 | verticalAlign: "top",
877 | backgroundColor: "transparent"
878 | },
879 | dropdown: {
880 | position: "absolute",
881 | top: "100%",
882 | left: "0",
883 | zIndex: "100",
884 | display: "none"
885 | }
886 | };
887 | if (utils.isMsie()) {
888 | utils.mixin(css.query, {
889 | backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
890 | });
891 | }
892 | if (utils.isMsie() && utils.isMsie() <= 7) {
893 | utils.mixin(css.wrapper, {
894 | display: "inline",
895 | zoom: "1"
896 | });
897 | utils.mixin(css.query, {
898 | marginTop: "-1px"
899 | });
900 | }
901 | function TypeaheadView(o) {
902 | var $menu, $input, $hint;
903 | utils.bindAll(this);
904 | this.$node = buildDomStructure(o.input);
905 | this.datasets = o.datasets;
906 | this.dir = null;
907 | this.eventBus = o.eventBus;
908 | $menu = this.$node.find(".tt-dropdown-menu");
909 | $input = this.$node.find(".tt-query");
910 | $hint = this.$node.find(".tt-hint");
911 | this.dropdownView = new DropdownView({
912 | menu: $menu
913 | }).on("suggestionSelected", this._handleSelection).on("cursorMoved", this._clearHint).on("cursorMoved", this._setInputValueToSuggestionUnderCursor).on("cursorRemoved", this._setInputValueToQuery).on("cursorRemoved", this._updateHint).on("suggestionsRendered", this._updateHint).on("opened", this._updateHint).on("closed", this._clearHint).on("opened closed", this._propagateEvent);
914 | this.inputView = new InputView({
915 | input: $input,
916 | hint: $hint
917 | }).on("focused", this._openDropdown).on("blured", this._closeDropdown).on("blured", this._setInputValueToQuery).on("enterKeyed tabKeyed", this._handleSelection).on("queryChanged", this._clearHint).on("queryChanged", this._clearSuggestions).on("queryChanged", this._getSuggestions).on("whitespaceChanged", this._updateHint).on("queryChanged whitespaceChanged", this._openDropdown).on("queryChanged whitespaceChanged", this._setLanguageDirection).on("escKeyed", this._closeDropdown).on("escKeyed", this._setInputValueToQuery).on("tabKeyed upKeyed downKeyed", this._managePreventDefault).on("upKeyed downKeyed", this._moveDropdownCursor).on("upKeyed downKeyed", this._openDropdown).on("tabKeyed leftKeyed rightKeyed", this._autocomplete);
918 | }
919 | utils.mixin(TypeaheadView.prototype, EventTarget, {
920 | _managePreventDefault: function(e) {
921 | var $e = e.data, hint, inputValue, preventDefault = false;
922 | switch (e.type) {
923 | case "tabKeyed":
924 | hint = this.inputView.getHintValue();
925 | inputValue = this.inputView.getInputValue();
926 | preventDefault = hint && hint !== inputValue;
927 | break;
928 |
929 | case "upKeyed":
930 | case "downKeyed":
931 | preventDefault = !$e.shiftKey && !$e.ctrlKey && !$e.metaKey;
932 | break;
933 | }
934 | preventDefault && $e.preventDefault();
935 | },
936 | _setLanguageDirection: function() {
937 | var dir = this.inputView.getLanguageDirection();
938 | if (dir !== this.dir) {
939 | this.dir = dir;
940 | this.$node.css("direction", dir);
941 | this.dropdownView.setLanguageDirection(dir);
942 | }
943 | },
944 | _updateHint: function() {
945 | var suggestion = this.dropdownView.getFirstSuggestion(), hint = suggestion ? suggestion.value : null, dropdownIsVisible = this.dropdownView.isVisible(), inputHasOverflow = this.inputView.isOverflow(), inputValue, query, escapedQuery, beginsWithQuery, match;
946 | if (hint && dropdownIsVisible && !inputHasOverflow) {
947 | inputValue = this.inputView.getInputValue();
948 | query = inputValue.replace(/\s{2,}/g, " ").replace(/^\s+/g, "");
949 | escapedQuery = utils.escapeRegExChars(query);
950 | beginsWithQuery = new RegExp("^(?:" + escapedQuery + ")(.*$)", "i");
951 | match = beginsWithQuery.exec(hint);
952 | this.inputView.setHintValue(inputValue + (match ? match[1] : ""));
953 | }
954 | },
955 | _clearHint: function() {
956 | this.inputView.setHintValue("");
957 | },
958 | _clearSuggestions: function() {
959 | this.dropdownView.clearSuggestions();
960 | },
961 | _setInputValueToQuery: function() {
962 | this.inputView.setInputValue(this.inputView.getQuery());
963 | },
964 | _setInputValueToSuggestionUnderCursor: function(e) {
965 | var suggestion = e.data;
966 | this.inputView.setInputValue(suggestion.value, true);
967 | },
968 | _openDropdown: function() {
969 | this.dropdownView.open();
970 | },
971 | _closeDropdown: function(e) {
972 | this.dropdownView[e.type === "blured" ? "closeUnlessMouseIsOverDropdown" : "close"]();
973 | },
974 | _moveDropdownCursor: function(e) {
975 | var $e = e.data;
976 | if (!$e.shiftKey && !$e.ctrlKey && !$e.metaKey) {
977 | this.dropdownView[e.type === "upKeyed" ? "moveCursorUp" : "moveCursorDown"]();
978 | }
979 | },
980 | _handleSelection: function(e) {
981 | var byClick = e.type === "suggestionSelected", suggestion = byClick ? e.data : this.dropdownView.getSuggestionUnderCursor();
982 | if (suggestion) {
983 | this.inputView.setInputValue(suggestion.value);
984 | byClick ? this.inputView.focus() : e.data.preventDefault();
985 | byClick && utils.isMsie() ? utils.defer(this.dropdownView.close) : this.dropdownView.close();
986 | this.eventBus.trigger("selected", suggestion.datum, suggestion.dataset);
987 | }
988 | },
989 | _getSuggestions: function() {
990 | var that = this, query = this.inputView.getQuery();
991 | if (utils.isBlankString(query)) {
992 | return;
993 | }
994 | utils.each(this.datasets, function(i, dataset) {
995 | dataset.getSuggestions(query, function(suggestions) {
996 | if (query === that.inputView.getQuery()) {
997 | that.dropdownView.renderSuggestions(dataset, suggestions);
998 | }
999 | });
1000 | });
1001 | },
1002 | _autocomplete: function(e) {
1003 | var isCursorAtEnd, ignoreEvent, query, hint, suggestion;
1004 | if (e.type === "rightKeyed" || e.type === "leftKeyed") {
1005 | isCursorAtEnd = this.inputView.isCursorAtEnd();
1006 | ignoreEvent = this.inputView.getLanguageDirection() === "ltr" ? e.type === "leftKeyed" : e.type === "rightKeyed";
1007 | if (!isCursorAtEnd || ignoreEvent) {
1008 | return;
1009 | }
1010 | }
1011 | query = this.inputView.getQuery();
1012 | hint = this.inputView.getHintValue();
1013 | if (hint !== "" && query !== hint) {
1014 | suggestion = this.dropdownView.getFirstSuggestion();
1015 | this.inputView.setInputValue(suggestion.value);
1016 | this.eventBus.trigger("autocompleted", suggestion.datum, suggestion.dataset);
1017 | }
1018 | },
1019 | _propagateEvent: function(e) {
1020 | this.eventBus.trigger(e.type);
1021 | },
1022 | destroy: function() {
1023 | this.inputView.destroy();
1024 | this.dropdownView.destroy();
1025 | destroyDomStructure(this.$node);
1026 | this.$node = null;
1027 | },
1028 | setQuery: function(query) {
1029 | this.inputView.setQuery(query);
1030 | this.inputView.setInputValue(query);
1031 | this._clearHint();
1032 | this._clearSuggestions();
1033 | this._getSuggestions();
1034 | }
1035 | });
1036 | return TypeaheadView;
1037 | function buildDomStructure(input) {
1038 | var $wrapper = $(html.wrapper), $dropdown = $(html.dropdown), $input = $(input), $hint = $(html.hint);
1039 | $wrapper = $wrapper.css(css.wrapper);
1040 | $dropdown = $dropdown.css(css.dropdown);
1041 | $hint.css(css.hint).css({
1042 | backgroundAttachment: $input.css("background-attachment"),
1043 | backgroundClip: $input.css("background-clip"),
1044 | backgroundColor: $input.css("background-color"),
1045 | backgroundImage: $input.css("background-image"),
1046 | backgroundOrigin: $input.css("background-origin"),
1047 | backgroundPosition: $input.css("background-position"),
1048 | backgroundRepeat: $input.css("background-repeat"),
1049 | backgroundSize: $input.css("background-size")
1050 | });
1051 | $input.data("ttAttrs", {
1052 | dir: $input.attr("dir"),
1053 | autocomplete: $input.attr("autocomplete"),
1054 | spellcheck: $input.attr("spellcheck"),
1055 | style: $input.attr("style")
1056 | });
1057 | $input.addClass("tt-query").attr({
1058 | autocomplete: "off",
1059 | spellcheck: false
1060 | }).css(css.query);
1061 | try {
1062 | !$input.attr("dir") && $input.attr("dir", "auto");
1063 | } catch (e) {}
1064 | return $input.wrap($wrapper).parent().prepend($hint).append($dropdown);
1065 | }
1066 | function destroyDomStructure($node) {
1067 | var $input = $node.find(".tt-query");
1068 | utils.each($input.data("ttAttrs"), function(key, val) {
1069 | utils.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
1070 | });
1071 | $input.detach().removeData("ttAttrs").removeClass("tt-query").insertAfter($node);
1072 | $node.remove();
1073 | }
1074 | }();
1075 | (function() {
1076 | var cache = {}, viewKey = "ttView", methods;
1077 | methods = {
1078 | initialize: function(datasetDefs) {
1079 | var datasets;
1080 | datasetDefs = utils.isArray(datasetDefs) ? datasetDefs : [ datasetDefs ];
1081 | if (datasetDefs.length === 0) {
1082 | $.error("no datasets provided");
1083 | }
1084 | datasets = utils.map(datasetDefs, function(o) {
1085 | var dataset = cache[o.name] ? cache[o.name] : new Dataset(o);
1086 | if (o.name) {
1087 | cache[o.name] = dataset;
1088 | }
1089 | return dataset;
1090 | });
1091 | return this.each(initialize);
1092 | function initialize() {
1093 | var $input = $(this), deferreds, eventBus = new EventBus({
1094 | el: $input
1095 | });
1096 | deferreds = utils.map(datasets, function(dataset) {
1097 | return dataset.initialize();
1098 | });
1099 | $input.data(viewKey, new TypeaheadView({
1100 | input: $input,
1101 | eventBus: eventBus = new EventBus({
1102 | el: $input
1103 | }),
1104 | datasets: datasets
1105 | }));
1106 | $.when.apply($, deferreds).always(function() {
1107 | utils.defer(function() {
1108 | eventBus.trigger("initialized");
1109 | });
1110 | });
1111 | }
1112 | },
1113 | destroy: function() {
1114 | return this.each(destroy);
1115 | function destroy() {
1116 | var $this = $(this), view = $this.data(viewKey);
1117 | if (view) {
1118 | view.destroy();
1119 | $this.removeData(viewKey);
1120 | }
1121 | }
1122 | },
1123 | setQuery: function(query) {
1124 | return this.each(setQuery);
1125 | function setQuery() {
1126 | var view = $(this).data(viewKey);
1127 | view && view.setQuery(query);
1128 | }
1129 | }
1130 | };
1131 | jQuery.fn.typeahead = function(method) {
1132 | if (methods[method]) {
1133 | return methods[method].apply(this, [].slice.call(arguments, 1));
1134 | } else {
1135 | return methods.initialize.apply(this, arguments);
1136 | }
1137 | };
1138 | })();
1139 | })(window.jQuery);
--------------------------------------------------------------------------------
/app/assets/javascripts/bootstrap-editable.min.js:
--------------------------------------------------------------------------------
1 | /*! X-editable - v1.5.1
2 | * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
3 | * http://github.com/vitalets/x-editable
4 | * Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
5 | !function(a){"use strict";var b=function(b,c){this.options=a.extend({},a.fn.editableform.defaults,c),this.$div=a(b),this.options.scope||(this.options.scope=this)};b.prototype={constructor:b,initInput:function(){this.input=this.options.input,this.value=this.input.str2value(this.options.value),this.input.prerender()},initTemplate:function(){this.$form=a(a.fn.editableform.template)},initButtons:function(){var b=this.$form.find(".editable-buttons");b.append(a.fn.editableform.buttons),"bottom"===this.options.showbuttons&&b.addClass("editable-buttons-bottom")},render:function(){this.$loading=a(a.fn.editableform.loading),this.$div.empty().append(this.$loading),this.initTemplate(),this.options.showbuttons?this.initButtons():this.$form.find(".editable-buttons").remove(),this.showLoading(),this.isSaving=!1,this.$div.triggerHandler("rendering"),this.initInput(),this.$form.find("div.editable-input").append(this.input.$tpl),this.$div.append(this.$form),a.when(this.input.render()).then(a.proxy(function(){if(this.options.showbuttons||this.input.autosubmit(),this.$form.find(".editable-cancel").click(a.proxy(this.cancel,this)),this.input.error)this.error(this.input.error),this.$form.find(".editable-submit").attr("disabled",!0),this.input.$input.attr("disabled",!0),this.$form.submit(function(a){a.preventDefault()});else{this.error(!1),this.input.$input.removeAttr("disabled"),this.$form.find(".editable-submit").removeAttr("disabled");var b=null===this.value||void 0===this.value||""===this.value?this.options.defaultValue:this.value;this.input.value2input(b),this.$form.submit(a.proxy(this.submit,this))}this.$div.triggerHandler("rendered"),this.showForm(),this.input.postrender&&this.input.postrender()},this))},cancel:function(){this.$div.triggerHandler("cancel")},showLoading:function(){var a,b;this.$form?(a=this.$form.outerWidth(),b=this.$form.outerHeight(),a&&this.$loading.width(a),b&&this.$loading.height(b),this.$form.hide()):(a=this.$loading.parent().width(),a&&this.$loading.width(a)),this.$loading.show()},showForm:function(a){this.$loading.hide(),this.$form.show(),a!==!1&&this.input.activate(),this.$div.triggerHandler("show")},error:function(b){var c,d=this.$form.find(".control-group"),e=this.$form.find(".editable-error-block");if(b===!1)d.removeClass(a.fn.editableform.errorGroupClass),e.removeClass(a.fn.editableform.errorBlockClass).empty().hide();else{if(b){c=(""+b).split("\n");for(var f=0;f
").text(c[f]).html();b=c.join("
")}d.addClass(a.fn.editableform.errorGroupClass),e.addClass(a.fn.editableform.errorBlockClass).html(b).show()}},submit:function(b){b.stopPropagation(),b.preventDefault();var c=this.input.input2value(),d=this.validate(c);if("object"===a.type(d)&&void 0!==d.newValue){if(c=d.newValue,this.input.value2input(c),"string"==typeof d.msg)return this.error(d.msg),this.showForm(),void 0}else if(d)return this.error(d),this.showForm(),void 0;if(!this.options.savenochange&&this.input.value2str(c)==this.input.value2str(this.value))return this.$div.triggerHandler("nochange"),void 0;var e=this.input.value2submit(c);this.isSaving=!0,a.when(this.save(e)).done(a.proxy(function(a){this.isSaving=!1;var b="function"==typeof this.options.success?this.options.success.call(this.options.scope,a,c):null;return b===!1?(this.error(!1),this.showForm(!1),void 0):"string"==typeof b?(this.error(b),this.showForm(),void 0):(b&&"object"==typeof b&&b.hasOwnProperty("newValue")&&(c=b.newValue),this.error(!1),this.value=c,this.$div.triggerHandler("save",{newValue:c,submitValue:e,response:a}),void 0)},this)).fail(a.proxy(function(a){this.isSaving=!1;var b;b="function"==typeof this.options.error?this.options.error.call(this.options.scope,a,c):"string"==typeof a?a:a.responseText||a.statusText||"Unknown error!",this.error(b),this.showForm()},this))},save:function(b){this.options.pk=a.fn.editableutils.tryParseJson(this.options.pk,!0);var c,d="function"==typeof this.options.pk?this.options.pk.call(this.options.scope):this.options.pk,e=!!("function"==typeof this.options.url||this.options.url&&("always"===this.options.send||"auto"===this.options.send&&null!==d&&void 0!==d));return e?(this.showLoading(),c={name:this.options.name||"",value:b,pk:d},"function"==typeof this.options.params?c=this.options.params.call(this.options.scope,c):(this.options.params=a.fn.editableutils.tryParseJson(this.options.params,!0),a.extend(c,this.options.params)),"function"==typeof this.options.url?this.options.url.call(this.options.scope,c):a.ajax(a.extend({url:this.options.url,data:c,type:"POST"},this.options.ajaxOptions))):void 0},validate:function(a){return void 0===a&&(a=this.value),"function"==typeof this.options.validate?this.options.validate.call(this.options.scope,a):void 0},option:function(a,b){a in this.options&&(this.options[a]=b),"value"===a&&this.setValue(b)},setValue:function(a,b){this.value=b?this.input.str2value(a):a,this.$form&&this.$form.is(":visible")&&this.input.value2input(this.value)}},a.fn.editableform=function(c){var d=arguments;return this.each(function(){var e=a(this),f=e.data("editableform"),g="object"==typeof c&&c;f||e.data("editableform",f=new b(this,g)),"string"==typeof c&&f[c].apply(f,Array.prototype.slice.call(d,1))})},a.fn.editableform.Constructor=b,a.fn.editableform.defaults={type:"text",url:null,params:null,name:null,pk:null,value:null,defaultValue:null,send:"auto",validate:null,success:null,error:null,ajaxOptions:null,showbuttons:!0,scope:null,savenochange:!1},a.fn.editableform.template='',a.fn.editableform.loading='',a.fn.editableform.buttons='',a.fn.editableform.errorGroupClass=null,a.fn.editableform.errorBlockClass="editable-error",a.fn.editableform.engine="jquery"}(window.jQuery),function(a){"use strict";a.fn.editableutils={inherit:function(a,b){var c=function(){};c.prototype=b.prototype,a.prototype=new c,a.prototype.constructor=a,a.superclass=b.prototype},setCursorPosition:function(a,b){if(a.setSelectionRange)a.setSelectionRange(b,b);else if(a.createTextRange){var c=a.createTextRange();c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",b),c.select()}},tryParseJson:function(a,b){if("string"==typeof a&&a.length&&a.match(/^[\{\[].*[\}\]]$/))if(b)try{a=new Function("return "+a)()}catch(c){}finally{return a}else a=new Function("return "+a)();return a},sliceObj:function(b,c,d){var e,f,g={};if(!a.isArray(c)||!c.length)return g;for(var h=0;h").text(b).html()},itemsByValue:function(b,c,d){if(!c||null===b)return[];if("function"!=typeof d){var e=d||"value";d=function(a){return a[e]}}var f=a.isArray(b),g=[],h=this;return a.each(c,function(c,e){if(e.children)g=g.concat(h.itemsByValue(b,e.children,d));else if(f)a.grep(b,function(a){return a==(e&&"object"==typeof e?d(e):e)}).length&&g.push(e);else{var i=e&&"object"==typeof e?d(e):e;b==i&&g.push(e)}}),g},createInput:function(b){var c,d,e,f=b.type;return"date"===f&&("inline"===b.mode?a.fn.editabletypes.datefield?f="datefield":a.fn.editabletypes.dateuifield&&(f="dateuifield"):a.fn.editabletypes.date?f="date":a.fn.editabletypes.dateui&&(f="dateui"),"date"!==f||a.fn.editabletypes.date||(f="combodate")),"datetime"===f&&"inline"===b.mode&&(f="datetimefield"),"wysihtml5"!==f||a.fn.editabletypes[f]||(f="textarea"),"function"==typeof a.fn.editabletypes[f]?(c=a.fn.editabletypes[f],d=this.sliceObj(b,this.objectKeys(c.defaults)),e=new c(d)):(a.error("Unknown type: "+f),!1)},supportsTransitions:function(){var a=document.body||document.documentElement,b=a.style,c="transition",d=["Moz","Webkit","Khtml","O","ms"];if("string"==typeof b[c])return!0;c=c.charAt(0).toUpperCase()+c.substr(1);for(var e=0;e"),this.tip().is(this.innerCss)?this.tip().append(this.$form):this.tip().find(this.innerCss).append(this.$form),this.renderForm()},hide:function(a){if(this.tip()&&this.tip().is(":visible")&&this.$element.hasClass("editable-open")){if(this.$form.data("editableform").isSaving)return this.delayedHide={reason:a},void 0;this.delayedHide=!1,this.$element.removeClass("editable-open"),this.innerHide(),this.$element.triggerHandler("hidden",a||"manual")}},innerShow:function(){},innerHide:function(){},toggle:function(a){this.container()&&this.tip()&&this.tip().is(":visible")?this.hide():this.show(a)},setPosition:function(){},save:function(a,b){this.$element.triggerHandler("save",b),this.hide("save")},option:function(a,b){this.options[a]=b,a in this.containerOptions?(this.containerOptions[a]=b,this.setContainerOption(a,b)):(this.formOptions[a]=b,this.$form&&this.$form.editableform("option",a,b))},setContainerOption:function(a,b){this.call("option",a,b)},destroy:function(){this.hide(),this.innerDestroy(),this.$element.off("destroyed"),this.$element.removeData("editableContainer")},innerDestroy:function(){},closeOthers:function(b){a(".editable-open").each(function(c,d){if(d!==b&&!a(d).find(b).length){var e=a(d),f=e.data("editableContainer");f&&("cancel"===f.options.onblur?e.data("editableContainer").hide("onblur"):"submit"===f.options.onblur&&e.data("editableContainer").tip().find("form").submit())}})},activate:function(){this.tip&&this.tip().is(":visible")&&this.$form&&this.$form.data("editableform").input.activate()}},a.fn.editableContainer=function(d){var e=arguments;return this.each(function(){var f=a(this),g="editableContainer",h=f.data(g),i="object"==typeof d&&d,j="inline"===i.mode?c:b;h||f.data(g,h=new j(this,i)),"string"==typeof d&&h[d].apply(h,Array.prototype.slice.call(e,1))})},a.fn.editableContainer.Popup=b,a.fn.editableContainer.Inline=c,a.fn.editableContainer.defaults={value:null,placement:"top",autohide:!0,onblur:"cancel",anim:!1,mode:"popup"},jQuery.event.special.destroyed={remove:function(a){a.handler&&a.handler()}}}(window.jQuery),function(a){"use strict";a.extend(a.fn.editableContainer.Inline.prototype,a.fn.editableContainer.Popup.prototype,{containerName:"editableform",innerCss:".editable-inline",containerClass:"editable-container editable-inline",initContainer:function(){this.$tip=a(""),this.options.anim||(this.options.anim=0)},splitOptions:function(){this.containerOptions={},this.formOptions=this.options},tip:function(){return this.$tip},innerShow:function(){this.$element.hide(),this.tip().insertAfter(this.$element).show()},innerHide:function(){this.$tip.hide(this.options.anim,a.proxy(function(){this.$element.show(),this.innerDestroy()},this))},innerDestroy:function(){this.tip()&&this.tip().empty().remove()}})}(window.jQuery),function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.editable.defaults,c,a.fn.editableutils.getConfigData(this.$element)),this.options.selector?this.initLive():this.init(),this.options.highlight&&!a.fn.editableutils.supportsTransitions()&&(this.options.highlight=!1)};b.prototype={constructor:b,init:function(){var b,c=!1;if(this.options.name=this.options.name||this.$element.attr("id"),this.options.scope=this.$element[0],this.input=a.fn.editableutils.createInput(this.options),this.input){switch(void 0===this.options.value||null===this.options.value?(this.value=this.input.html2value(a.trim(this.$element.html())),c=!0):(this.options.value=a.fn.editableutils.tryParseJson(this.options.value,!0),this.value="string"==typeof this.options.value?this.input.str2value(this.options.value):this.options.value),this.$element.addClass("editable"),"textarea"===this.input.type&&this.$element.addClass("editable-pre-wrapped"),"manual"!==this.options.toggle?(this.$element.addClass("editable-click"),this.$element.on(this.options.toggle+".editable",a.proxy(function(a){if(this.options.disabled||a.preventDefault(),"mouseenter"===this.options.toggle)this.show();else{var b="click"!==this.options.toggle;this.toggle(b)}},this))):this.$element.attr("tabindex",-1),"function"==typeof this.options.display&&(this.options.autotext="always"),this.options.autotext){case"always":b=!0;break;case"auto":b=!a.trim(this.$element.text()).length&&null!==this.value&&void 0!==this.value&&!c;break;default:b=!1}a.when(b?this.render():!0).then(a.proxy(function(){this.options.disabled?this.disable():this.enable(),this.$element.triggerHandler("init",this)},this))}},initLive:function(){var b=this.options.selector;this.options.selector=!1,this.options.autotext="never",this.$element.on(this.options.toggle+".editable",b,a.proxy(function(b){var c=a(b.target);c.data("editable")||(c.hasClass(this.options.emptyclass)&&c.empty(),c.editable(this.options).trigger(b))},this))},render:function(a){return this.options.display!==!1?this.input.value2htmlFinal?this.input.value2html(this.value,this.$element[0],this.options.display,a):"function"==typeof this.options.display?this.options.display.call(this.$element[0],this.value,a):this.input.value2html(this.value,this.$element[0]):void 0},enable:function(){this.options.disabled=!1,this.$element.removeClass("editable-disabled"),this.handleEmpty(this.isEmpty),"manual"!==this.options.toggle&&"-1"===this.$element.attr("tabindex")&&this.$element.removeAttr("tabindex")},disable:function(){this.options.disabled=!0,this.hide(),this.$element.addClass("editable-disabled"),this.handleEmpty(this.isEmpty),this.$element.attr("tabindex",-1)},toggleDisabled:function(){this.options.disabled?this.enable():this.disable()},option:function(b,c){return b&&"object"==typeof b?(a.each(b,a.proxy(function(b,c){this.option(a.trim(b),c)},this)),void 0):(this.options[b]=c,"disabled"===b?c?this.disable():this.enable():("value"===b&&this.setValue(c),this.container&&this.container.option(b,c),this.input.option&&this.input.option(b,c),void 0))},handleEmpty:function(b){this.options.display!==!1&&(this.isEmpty=void 0!==b?b:"function"==typeof this.input.isEmpty?this.input.isEmpty(this.$element):""===a.trim(this.$element.html()),this.options.disabled?this.isEmpty&&(this.$element.empty(),this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass)):this.isEmpty?(this.$element.html(this.options.emptytext),this.options.emptyclass&&this.$element.addClass(this.options.emptyclass)):this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass))},show:function(b){if(!this.options.disabled){if(this.container){if(this.container.tip().is(":visible"))return}else{var c=a.extend({},this.options,{value:this.value,input:this.input});this.$element.editableContainer(c),this.$element.on("save.internal",a.proxy(this.save,this)),this.container=this.$element.data("editableContainer")}this.container.show(b)}},hide:function(){this.container&&this.container.hide()},toggle:function(a){this.container&&this.container.tip().is(":visible")?this.hide():this.show(a)},save:function(a,b){if(this.options.unsavedclass){var c=!1;c=c||"function"==typeof this.options.url,c=c||this.options.display===!1,c=c||void 0!==b.response,c=c||this.options.savenochange&&this.input.value2str(this.value)!==this.input.value2str(b.newValue),c?this.$element.removeClass(this.options.unsavedclass):this.$element.addClass(this.options.unsavedclass)}if(this.options.highlight){var d=this.$element,e=d.css("background-color");d.css("background-color",this.options.highlight),setTimeout(function(){"transparent"===e&&(e=""),d.css("background-color",e),d.addClass("editable-bg-transition"),setTimeout(function(){d.removeClass("editable-bg-transition")},1700)},10)}this.setValue(b.newValue,!1,b.response)},validate:function(){return"function"==typeof this.options.validate?this.options.validate.call(this,this.value):void 0},setValue:function(b,c,d){this.value=c?this.input.str2value(b):b,this.container&&this.container.option("value",this.value),a.when(this.render(d)).then(a.proxy(function(){this.handleEmpty()},this))},activate:function(){this.container&&this.container.activate()},destroy:function(){this.disable(),this.container&&this.container.destroy(),this.input.destroy(),"manual"!==this.options.toggle&&(this.$element.removeClass("editable-click"),this.$element.off(this.options.toggle+".editable")),this.$element.off("save.internal"),this.$element.removeClass("editable editable-open editable-disabled"),this.$element.removeData("editable")}},a.fn.editable=function(c){var d={},e=arguments,f="editable";switch(c){case"validate":return this.each(function(){var b,c=a(this),e=c.data(f);e&&(b=e.validate())&&(d[e.options.name]=b)}),d;case"getValue":return 2===arguments.length&&arguments[1]===!0?d=this.eq(0).data(f).value:this.each(function(){var b=a(this),c=b.data(f);c&&void 0!==c.value&&null!==c.value&&(d[c.options.name]=c.input.value2submit(c.value))}),d;case"submit":var g=arguments[1]||{},h=this,i=this.editable("validate");if(a.isEmptyObject(i)){var j={};if(1===h.length){var k=h.data("editable"),l={name:k.options.name||"",value:k.input.value2submit(k.value),pk:"function"==typeof k.options.pk?k.options.pk.call(k.options.scope):k.options.pk};"function"==typeof k.options.params?l=k.options.params.call(k.options.scope,l):(k.options.params=a.fn.editableutils.tryParseJson(k.options.params,!0),a.extend(l,k.options.params)),j={url:k.options.url,data:l,type:"POST"},g.success=g.success||k.options.success,g.error=g.error||k.options.error}else{var m=this.editable("getValue");j={url:g.url,data:m,type:"POST"}}j.success="function"==typeof g.success?function(a){g.success.call(h,a,g)}:a.noop,j.error="function"==typeof g.error?function(){g.error.apply(h,arguments)}:a.noop,g.ajaxOptions&&a.extend(j,g.ajaxOptions),g.data&&a.extend(j.data,g.data),a.ajax(j)}else"function"==typeof g.error&&g.error.call(h,i);return this}return this.each(function(){var d=a(this),g=d.data(f),h="object"==typeof c&&c;return h&&h.selector?(g=new b(this,h),void 0):(g||d.data(f,g=new b(this,h)),"string"==typeof c&&g[c].apply(g,Array.prototype.slice.call(e,1)),void 0)})},a.fn.editable.defaults={type:"text",disabled:!1,toggle:"click",emptytext:"Empty",autotext:"auto",value:null,display:null,emptyclass:"editable-empty",unsavedclass:"editable-unsaved",selector:null,highlight:"#FFFF80"}}(window.jQuery),function(a){"use strict";a.fn.editabletypes={};var b=function(){};b.prototype={init:function(b,c,d){this.type=b,this.options=a.extend({},d,c)},prerender:function(){this.$tpl=a(this.options.tpl),this.$input=this.$tpl,this.$clear=null,this.error=null},render:function(){},value2html:function(b,c){a(c)[this.options.escape?"text":"html"](a.trim(b))},html2value:function(b){return a("").html(b).text()},value2str:function(a){return a},str2value:function(a){return a},value2submit:function(a){return a},value2input:function(a){this.$input.val(a)},input2value:function(){return this.$input.val()},activate:function(){this.$input.is(":visible")&&this.$input.focus()},clear:function(){this.$input.val(null)},escape:function(b){return a("
").text(b).html()},autosubmit:function(){},destroy:function(){},setClass:function(){this.options.inputclass&&this.$input.addClass(this.options.inputclass)},setAttr:function(a){void 0!==this.options[a]&&null!==this.options[a]&&this.$input.attr(a,this.options[a])},option:function(a,b){this.options[a]=b}},b.defaults={tpl:"",inputclass:null,escape:!0,scope:null,showbuttons:!0},a.extend(a.fn.editabletypes,{abstractinput:b})}(window.jQuery),function(a){"use strict";var b=function(){};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){var b=a.Deferred();return this.error=null,this.onSourceReady(function(){this.renderList(),b.resolve()},function(){this.error=this.options.sourceError,b.resolve()}),b.promise()},html2value:function(){return null},value2html:function(b,c,d,e){var f=a.Deferred(),g=function(){"function"==typeof d?d.call(c,b,this.sourceData,e):this.value2htmlFinal(b,c),f.resolve()};return null===b?g.call(this):this.onSourceReady(g,function(){f.resolve()}),f.promise()},onSourceReady:function(b,c){var d;if(a.isFunction(this.options.source)?(d=this.options.source.call(this.options.scope),this.sourceData=null):d=this.options.source,this.options.sourceCache&&a.isArray(this.sourceData))return b.call(this),void 0;try{d=a.fn.editableutils.tryParseJson(d,!1)}catch(e){return c.call(this),void 0}if("string"==typeof d){if(this.options.sourceCache){var f,g=d;if(a(document).data(g)||a(document).data(g,{}),f=a(document).data(g),f.loading===!1&&f.sourceData)return this.sourceData=f.sourceData,this.doPrepend(),b.call(this),void 0;if(f.loading===!0)return f.callbacks.push(a.proxy(function(){this.sourceData=f.sourceData,this.doPrepend(),b.call(this)},this)),f.err_callbacks.push(a.proxy(c,this)),void 0;f.loading=!0,f.callbacks=[],f.err_callbacks=[]}var h=a.extend({url:d,type:"get",cache:!1,dataType:"json",success:a.proxy(function(d){f&&(f.loading=!1),this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(f&&(f.sourceData=this.sourceData,a.each(f.callbacks,function(){this.call()})),this.doPrepend(),b.call(this)):(c.call(this),f&&a.each(f.err_callbacks,function(){this.call()}))},this),error:a.proxy(function(){c.call(this),f&&(f.loading=!1,a.each(f.err_callbacks,function(){this.call()}))},this)},this.options.sourceOptions);a.ajax(h)}else this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(this.doPrepend(),b.call(this)):c.call(this)},doPrepend:function(){null!==this.options.prepend&&void 0!==this.options.prepend&&(a.isArray(this.prependData)||(a.isFunction(this.options.prepend)&&(this.options.prepend=this.options.prepend.call(this.options.scope)),this.options.prepend=a.fn.editableutils.tryParseJson(this.options.prepend,!0),"string"==typeof this.options.prepend&&(this.options.prepend={"":this.options.prepend}),this.prependData=this.makeArray(this.options.prepend)),a.isArray(this.prependData)&&a.isArray(this.sourceData)&&(this.sourceData=this.prependData.concat(this.sourceData)))},renderList:function(){},value2htmlFinal:function(){},makeArray:function(b){var c,d,e,f,g=[];if(!b||"string"==typeof b)return null;if(a.isArray(b)){f=function(a,b){return d={value:a,text:b},c++>=2?!1:void 0};for(var h=0;h
1&&(e.children&&(e.children=this.makeArray(e.children)),g.push(e))):g.push({value:e,text:e})}else a.each(b,function(a,b){g.push({value:a,text:b})});return g},option:function(a,b){this.options[a]=b,"source"===a&&(this.sourceData=null),"prepend"===a&&(this.prependData=null)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{source:null,prepend:!1,sourceError:"Error when loading list",sourceCache:!0,sourceOptions:null}),a.fn.editabletypes.list=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("text",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.renderClear(),this.setClass(),this.setAttr("placeholder")},activate:function(){this.$input.is(":visible")&&(this.$input.focus(),a.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length),this.toggleClear&&this.toggleClear())},renderClear:function(){this.options.clear&&(this.$clear=a(''),this.$input.after(this.$clear).css("padding-right",24).keyup(a.proxy(function(b){if(!~a.inArray(b.keyCode,[40,38,9,13,27])){clearTimeout(this.t);var c=this;this.t=setTimeout(function(){c.toggleClear(b)},100)}},this)).parent().css("position","relative"),this.$clear.click(a.proxy(this.clear,this)))},postrender:function(){},toggleClear:function(){if(this.$clear){var a=this.$input.val().length,b=this.$clear.is(":visible");a&&!b&&this.$clear.show(),!a&&b&&this.$clear.hide()}},clear:function(){this.$clear.hide(),this.$input.val("").focus()}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'',placeholder:null,clear:!0}),a.fn.editabletypes.text=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("textarea",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass(),this.setAttr("placeholder"),this.setAttr("rows"),this.$input.keydown(function(b){b.ctrlKey&&13===b.which&&a(this).closest("form").submit()})},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:"",inputclass:"input-large",placeholder:null,rows:7}),a.fn.editabletypes.textarea=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("select",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){this.$input.empty();var b=function(c,d){var e;if(a.isArray(d))for(var f=0;f",e),d[f].children))):(e.value=d[f].value,d[f].disabled&&(e.disabled=!0),c.append(a("
awesome
comment!