if not document?
document =
getElementById: ->
attachEvent: ->
if not window?
window =
document: document
navigator:
userAgent: "Chrome" # TODO improve this
Copyright 2012-2017, Nooron Collaboratory, Inc http://nooron.com
if not document?
document =
getElementById: ->
attachEvent: ->
if not window?
window =
document: document
navigator:
userAgent: "Chrome" # TODO improve this
##
VALUETYPE_2_XSD =
boolean: "boolean"
date: "date" # ISO8601
datetime: "dateTime" # ISO8601
duration: "duration"
dollars: "decimal"
five_stars: "int"
html_snippet: "string" # TODO this should be escaped, how? encoded as base64?
integer: "int"
letter_grade: "string"
float: "float"
plain: "string"
timestamp: "timestamp" # TODO should this be 'timestamp'?
username: "string"
zero_to_one: "decimal"
agent_types: "string"
XSD_2_VALUETYPE = {}
xsd_type_to_valuetype = (xsd_type) ->
if not XSD_2_VALUETYPE[xsd_type]?
for k,v of VALUETYPE_2_XSD
if v is 'string'
k = 'plain'
XSD_2_VALUETYPE[v] = k
return XSD_2_VALUETYPE[xsd_type]
valuetype_to_xsd_type = (valuetype_id) ->
return datatype_to_xsd_type[valuetype_id]
localize_iso8601 = (date_str) ->
date = new Date(date_str)
minus = (d, i) -> new Date(d.getTime() - i)
localize = (d) -> d.toISOString().substr(0, 19)
return localize(minus(date, date.getTimezoneOffset()*60*1000))
validate_iso8601 = ->
throw_diff = (a, b) ->
if a isnt b
throw "#{a} isnt #{b}"
throw_diff(localize_iso8601('2017-04-17T23:34:03Z'), '2017-04-17T17:34:03')
throw_diff(localize_iso8601('2016-07-01T12:00:00Z'), '2016-07-01T06:00:00')
throw_diff(localize_iso8601('2016-07-01T12:00:00Z'), '2016-07-01T06:00:00')
return true
widget_html = """
<style type="text/css" class="ptwDynamicStyle"></style>
<script type="text/javascript">console.log("WIDGET_HTML");Ponderate.jQuery = jQuery.noConflict(true);</script>
<table class="ponderateTabularWidget" id="ptw__PNDR_ID">
<caption class="contentEditableInEditMode"></caption>
<thead>
<tr class="ptwControls criterionRow">
<td class="controls">
<div class="windowShade">
<span class="windowShadeHandle">══⇅════⇅══</span>
<span class="windowShadeLabel"></span>
</div>
<div>
<label class="authorizedUsersOnly editButton">
<input type="checkbox"/></label>
<input
class="editControl authorizedUsersOnly saveButton"
type="button" value="Save">
</div>
<div class="controls">
<div class="editControl authorizedUsersOnly addCriterionButton">
add Criterion</div>
<div class="editControl authorizedUsersOnly addCandidateButton">
add Candidate</div>
</div>
</td>
</tr>
</thead>
<tfoot>
<tr>
<td class="widenedByUnshadedCritCount" colspan="1">
<span class="createdBy securityLabel"></span>
<a style="display: none" class="poweredBy" href="http://nooron.com">Nooron</a>
</td>
</tr>
<tr class="editControl">
<td class="widenedByUnshadedCritCount" colspan="1" style="display:none">
<label><span class="securityLabel">embed:</span>
<input class="htmlToEmbed"></input></label><br>
</td>
</tr>
<tr class="editControl">
<td class="widenedByUnshadedCritCount securityTd" colspan="1">
<label><span class="securityLabel">readable by:</span>
<select class="readable_by" name="readable_by"></select></label>
<label><span class="securityLabel">writeable by:</span>
<select class="writeable_by" name="writeable_by"></select></label>
<span class="shareButton">share</span>
</td>
</tr>
</tfoot>
<tbody class="disableSelect">
</tbody>
</table>
"""
Ponderate = {} if typeof Ponderate is "undefined"
tabular_widget = (ptw_args) ->
SUPPORTED_BROWSERS = "Google Chrome and Apple Safari"
gEBCN = (parentElement, class_name, tag) ->
Extendeds function with performance improvements.
* by using a parentElement and the tag the class is on
* the list of elements to check is reduced.
*
* This function doesn't get bound to an object.
docList = undefined
matchArray = undefined
re = undefined
len = undefined
tag = tag or "*"
parentElement = parentElement or document
object could be passed instead of Id
if typeof(parentElement) is "string"
parentElement = document.getElementById(parentElement)
Get array of tags
if tag is "*"
docList = parentElement.all or parentElement.getElementsByTagName("*")
else
docList = parentElement.getElementsByTagName(tag)
Create a regular expression object for class
re = new RegExp("(?:^|\\s)" + class_name + "(?:\\s|$)")
Create output array
matchArray = new Array()
len = docList.length - 1
Populate output array from tag array
* do loop is faster than for loop
* albeit out is in reverse order
while len
matchArray[matchArray.length] = docList[len] if re.test(docList[len].className)
len--
return matchArray.reverse(); //if the order needs to forward
matchArray
cstmGetElementsByClassNameExt2 if (typeof document.getElementsByClassName !== ‘function’){ document.getElementsByClassName = gEBCN; }
sleep = (msec) ->
start_time = new Date()
a = 1 while new Date() - start_time < msec
is_undefined = (v) ->
no_val = undefined
typeof(v) is typeof(no_val)
is_defined = (v) ->
no_val = undefined
typeof(v) isnt typeof(no_val)
get_event_target = (e) ->
targ = undefined
e = window.event unless e
if e.target
targ = e.target
else targ = e.srcElement if e.srcElement
defeat Safari bug
targ = targ.parentNode if targ.nodeType is 3
targ
http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx console.log(navigator);
is_IE = navigator.userAgent.indexOf("MSIE") > -1
must_attachEvent = is_defined(document.attachEvent)
display_none = "{display:none;}"
copy_props_from_to_ = (pr, fr, to) ->
for i of pr
continue unless pr.hasOwnProperty(i)
k = pr[i]
to[k] = fr[k] if fr[k]
is_boolean = (b) ->
typeof(b) is typeof(true)
has_value = (v) ->
(typeof (v) isnt `undefined`) and (v isnt null) and (v isnt "")
ascending_cmp = (a, b) ->
if ((typeof(a) == typeof(true) && typeof(b) != typeof(true)) || (typeof(b) == typeof(true) && typeof(a) != typeof(true)) ) console.log(“type disparity:”,typeof(a),a,typeof(b),b);
return 0 if a is b
return 1 if a > b
-1 if a < b
descending_cmp = (a, b) ->
if ((typeof(a) == typeof(true) && typeof(b) != typeof(true)) || (typeof(b) == typeof(true) && typeof(a) != typeof(true)) ) console.log(“type disparity:”,typeof(a),a,typeof(b),b);
return 0 if a is b
return -1 if a > b
1 if a < b
on_obj_put_proto = (obj, proto) ->
proto.PROTO_WORKS = true
obj.__proto__ = proto
unless obj.PROTO_WORKS
for k of proto
obj[k] = proto[k]
delete proto.PROTO_WORKS
unicod =
writing_hand: "✍"
big_check: "✔"
big_X: "✖"
pencil_left: "✎"
black_up_pointing_triangle: "▲"
black_down_pointing_triangle: "▼"
ptw_defaults =
make_table_caption_draggable: false
PROTO_WORKS: true
table_id: "PNDR_ID"
vert_bar: "┃<br>"
basic_arrow: "┃<br>┃<br>▼"
svg_basic_arrow: "<img style=\"max-width:100%;max-height:100%\" src=\"http://upload.wikimedia.org/wikipedia/commons/f/ff/Arrow_south.svg\">"
XXbasic_arrow: "<img src=\"http://alpha.ponderate.com/images/arrow.svg\" height=\"100%\"/>"
basic_arrow: “
“ + ““
big_check: unicod.big_check
big_X: unicod.big_X
edit_icon: unicod.writing_hand
down_arrow: unicod.black_down_pointing_triangle
up_arrow: unicod.black_up_pointing_triangle
being_edited: false
interaction_mode: 'document' # vs 'spreadsheet'
pndr8_title: "Title of Ponderation"
_id: ""
has_unsaved_changes: false
show_edit_button: false
base_url: "http://alpha.ponderate.com"
stylesheet_link_tmpl: "<link title=\"SHEET_NAME\" rel=\"stylesheet\" href=\"BASE_URL/stylesheets/SHEET_NAME.css\"/>"
readable_by: "workgroup"
writeable_by: "workgroup"
criteria_have_grab_grip_cell: false # to enable a feature being worked on
display_candidate_link_edit_control: true
display_candidate_edit_control: false # contentEditable instead
display_candidate_delete_control: true
display_criterion_default_order_control: true
display_criterion_valuetype_control: true
candidate_label_editable: true
is_bookmarking_mode: false
candidate__target: "target=\"_blank\" "
if not ptw_args?
ptw_args = {}
on_obj_put_proto(ptw_args, ptw_defaults)
ptw_vars =
candidates_unsorted: true
criteria_by_row_idx: []
candidates_by_row_idx: []
candidates_by_their_id: {}
criteria_by_their_id: {}
candidates_by_url: {}
candidates_by_label: {}
submitted_bugs: []
num_crit_shaded: 0
the vars (contains the args and the defaults)
on_obj_put_proto(ptw_vars, ptw_args)
/////////////////////////////////////////////// CANDIDATE
candidate = (cand_spec) ->
cand_spec = cand_spec or {}
cand_spec.__proto__ =
dirty: false
unsorted: true
cand_spec.data_by_crit_id = {}
self =
dirty: (b) ->
if is_boolean(b)
cand_spec.dirty = b
cand_spec.dirty
unsorted: (b) ->
if is_boolean(b)
cand_spec.unsorted = b
pndr.candidates_unsorted(b)
cand_spec.unsorted
getElementsByClassName: (class_name, tag_hint) ->
if cand_spec.tr.getElementsByClassName
cand_spec.tr.getElementsByClassName class_name
else
gEBCN cand_spec.tr, class_name, tag_hint
focus_on_datum_after: (prev_datum) ->
FIXME find the next datum and ptw_vars. prev_datum.crit_id
add_cand_to_table: (args) ->
self.make_cand_table_elements()
self.register_cand()
self.add_column_for_each_criterion()
self.update_cand_visible()
id: (n) ->
cand_spec.id
tr: (tr) ->
if tr
cand_spec.tr = tr
cand_spec.row_idx = tr.sectionRowIndex
cand_spec.tr
idx: (n) ->
cand_spec.row_idx = n if is_defined(n)
cand_spec.row_idx
url: (u) ->
cand_spec.url = u if is_defined(u)
cand_spec.url
delete_url: (args) ->
delete cand_spec.url
get_ponder_id_from_url: ->
retval = self.url().split("/").reverse()[0]
alert(retval);
retval
pack_cand_for_saving: (args) ->
out =
label: cand_spec.label
id: cand_spec.id
out.url = cand_spec.url if cand_spec.url
out
data_for_saving: (args) ->
out = []
for crit_id of cand_spec.data_by_crit_id
a_datum = cand_spec.data_by_crit_id[crit_id]
if a_datum
json = a_datum.pack_for_saving()
out.push json if json
out
make_cand_table_elements: (args) ->
if is_undefined(cand_spec.row_idx)
cand_spec.row_idx = ptw_vars.candidate_rows.childElementCount
tr = ptw_vars.candidate_rows.insertRow(cand_spec.row_idx)
if (! tr.getElementsByClassName){tr.prototype.getElementsByClassName = cstmGetElementsByClassNameExt2;}
self.tr tr
tr.setAttribute "class", "candidateRow"
td_1 = tr.insertCell(0)
td_1.setAttribute "class", "candidateCell"
cand_label_span = document.createElement("span")
td_1.appendChild cand_label_span
cand_label_span.contentEditable = ptw_vars.candidate_label_editable
cand_label_span.setAttribute "class", "candidateLabel contentEditableInEditMode"
cand_label_span.onblur = pndr.onblur_candidate_label_handler # evt when focus leaves
if ptw_vars.candidate_click_callback
cand_label_span.onclick = ptw_vars.candidate_click_callback
if ptw_vars.display_candidate_delete_control
del_butt = document.createElement("span")
del_butt.className = "candidateDeleteButton editControl"
del_butt.innerHTML = unicod.big_X
del_butt.onclick = pndr.del_candidate_handler
td_1.appendChild del_butt
if ptw_vars.display_candidate_link_edit_control
link_edit_butt = document.createElement("span")
link_edit_butt.className = "candidateLinkEditButton editControl"
link_edit_butt.innerHTML = "↬" # BROKEN CIRCLE WITH NORTHWEST ARROW
link_edit_butt.onclick = pndr.edit_candidate_link_handler
td_1.appendChild link_edit_butt
if ptw_vars.display_candidate_edit_control
edit_butt = document.createElement("span")
edit_butt.className = "candidateEditButton editControl"
edit_butt.innerHTML = "✍" # WRITING HAND
td_1.appendChild edit_butt
if ptw_vars.candidate__drag_start_handler
if false # TODO put a default on ptw_vars.make_candidate_drag_handles
drag_handle = document.createElement("span")
drag_handle.className = "candidateDragHandle fa fa-reorder"
td_1.appendChild drag_handle
$(drag_handle).attr("style","background-color:yellow")
else
drag_handle = tr
$(drag_handle).draggable
refreshPositions: true
scroll: false
snapTolerance: 500
cursorAt:
top: 5
left: 5
helper: (e, ui) ->
elem_to_drag = e.target
if elem_to_drag.tagName isnt 'TD'
elem_to_drag = $(e.target).parent("td")
return $(elem_to_drag).clone().appendTo('body').
attr("class", "dnd_drag_helper").
css('zIndex', 5).
css('left', e.clientX). # position helper at mouse x location
css('top', e.clientY). # and in the y dimension too
show()
stop: ptw_vars.candidate__drop_handler
start: ptw_vars.candidate__drag_start_handler
##
$(drag_handle).draggable
simple_helper: "clone"
helper: (e, ui) ->
console.log e
return $(this).clone().appendTo('body').css('zIndex', 5).show()
handle: ".candidateDragHandle"
stop: ptw_vars.candidate__drop_handler
start: ptw_vars.candidate__drag_start_handler
## console.log ptw_vars.candidate__drag_start_handler
td_1.setAttribute 'id', cand_spec.id
remove: (args) ->
candidate_section = ptw_vars.candidate_rows
cand_spec.tr.parentNode.removeChild cand_spec.tr
delete ptw_vars.candidates_by_row_idx[cand_spec.row_idx]
delete ptw_vars.candidates_by_their_id[cand_spec.id]
idx = cand_spec.row_idx
while idx <= candidate_section.children.length
other_cand = ptw_vars.candidates_by_row_idx[idx]
if other_cand
other_cand.register_cand()
idx++
self.delete_data_from_cand()
TODO remove data update lower candidates so their row_idx is accurate re-register the remaining candidates in candidates_by_row_idx and candidates_by_their_id
delete_data_from_cand: (args) ->
for crit_id of cand_spec.data_by_crit_id
a_datum = cand_spec.data_by_crit_id[crit_id]
a_datum.crit_obj().forget_datum a_datum
register_cand: (args) ->
cand_spec.row_idx = cand_spec.tr.sectionRowIndex
ptw_vars.candidates_by_row_idx[cand_spec.row_idx] = self
ptw_vars.candidates_by_label[cand_spec.label] = self;
if (cand_spec.url){
ptw_vars.candidates_by_url[cand_spec.url] = self;
}
console.log(cand_spec.label,cand_spec.row_idx);
update_cand_visible: (args) ->
display_url = (cand_spec.url)
if pndr.is_bookmarking_mode()
a = document.createElement("a")
a.appendChild document.createTextNode(cand_spec.label)
a.onclick = pndr.choose_ponder_to_add_candidate_to_handler
a.setAttribute(‘onclick’,”alert(evt)”);
self.getElementsByClassName("candidateLabel")[0].appendChild a
else if display_url
url_on_ponderate = cand_spec.url[0] is "/"
target = (if url_on_ponderate then "" else ptw_vars.candidate__target)
FIXME remove all uses of ?EDIT var EDIT = (ptw_vars.show_edit_button && url_on_ponderate) ? “?EDIT”: ‘’; console.log(“EDIT=”+EDIT); +EDIT
self.getElementsByClassName("candidateLabel")[0].innerHTML = "<a " + target + "href=\"" + cand_spec.url + "\">" + cand_spec.label + "</a>" #"("+cand_spec.row_idx+')</a>';
else
self.getElementsByClassName("candidateLabel")[0].innerHTML = cand_spec.label #+ "("+cand_spec.row_idx+")";
add_column_for_each_criterion: (args) ->
num_crit_shown = pndr.get_num_crit_unshaded()
idx = 0
while idx < ptw_vars.criteria_by_row_idx.length
for (id in ptw_vars.criteria_by_their_id){
obj = ptw_vars.criteria_by_row_idx[idx]
var obj = ptw_vars.criteria_by_their_id[id]; console.log(‘add column:’,obj);
self.add_column crit_obj: obj
idx++
add_column: (args) ->
cell_index = cand_spec.tr.childElementCount - 1
td = cand_spec.tr.insertCell(cell_index)
css_classes = "eval"
if args.crit_obj.cells_visualizable()
css_classes += " ui-draggable"
td.setAttribute "draggable", true
td.setAttribute "class", css_classes #"eval"
a_datum = undefined
if pndr.being_edited()
a_datum = @ensure_datum_for_criterion(args.crit_obj)
else
a_datum = @datum_for_crit_id(args.crit_obj.id())
return unless a_datum
$(td).hide() if cell_index >= pndr.get_num_crit_unshaded()
a_datum.display_within td
a_datum.update_datum_display()
label: (n) ->
cand_spec.label = n if is_defined(n) and has_value(n)
cand_spec.label
add_datum_to_candidate: (d) ->
self.datum_for_crit_id(d.crit_id(), d)
self.discover_display_within_for_datum d
d.update_datum_display()
discover_display_within_for_datum: (d) ->
d.display_within cand_spec.tr.children[d.crit_obj().idx()] if d.crit_obj() unless d.display_within()
update_candidate_display: (args) ->
idx = 0
while idx < ptw_vars.criteria_by_row_idx.length
crit_obj = ptw_vars.criteria_by_row_idx[idx]
self.ensure_datum_for_criterion(crit_obj)
crit_id = crit_obj.id()
cand_spec.data_by_crit_id[crit_id].update_datum_display()
idx++
get_datum_by_crit_id: (crit_id) ->
cand_spec.data_by_crit_id[crit_id]
move_crit_datum_from_to_: (crit_obj, from_idx, to_idx) ->
remove_idx = undefined
if from_idx > to_idx
insert_idx = to_idx
remove_idx = from_idx + 1 # since it's shifted by insert
if from_idx < to_idx
remove_idx = from_idx
insert_idx = to_idx + 1
d_obj = cand_spec.data_by_crit_id[crit_obj.id()]
new_cell = cand_spec.tr.insertCell(insert_idx)
cand_spec.tr.removeChild cand_spec.tr.children[remove_idx]
if d_obj
d_obj.display_within new_cell
d_obj.update_datum_display()
ensure_datum_for_criterion: (crit_obj) ->
d_obj = cand_spec.data_by_crit_id[crit_obj.id()]
if d_obj
return d_obj
else
d = crit_obj.spawn_datum({cand_id: self.id()})
d = self.datum_for_crit_id(crit_obj.id(), d)
self.discover_display_within_for_datum(d)
return d
datum_for_crit_id: (crit_id, d) ->
if d
cand_spec.data_by_crit_id[d.crit_id()] = d
crit_obj = ptw_vars.criteria_by_their_id[d.crit_id()]
d.crit_obj crit_obj
d.cand_obj self
d.update_datum_display()
return cand_spec.data_by_crit_id[crit_id]
self
/////////////////////////////////////////////// DATUM
datum = (datum_spec) ->
self =
value_is_saveable: (args) ->
TODO review the logic in value_is_saveable
datum_spec.value isnt `undefined` and datum_spec.value isnt ""
pack_for_saving: (args) ->
if self.value_is_saveable()
return [datum_spec.cand_id, datum_spec.crit_id, self.get_saveable_value()]
get_display_value: (args) ->
self.crit_obj().crit_display_value(self)
get_editable_value: (args) ->
self.crit_obj().crit_editable_value(self)
get_saveable_value: (args) ->
self.crit_obj().crit_saveable_value(self)
get_sortable_value: (args) ->
self.crit_obj().crit_sortable_value(self)
datum_coerce_to_valuetype: (args) ->
self.crit_obj().crit_coerce_to_valuetype(self)
crit_id: (n) ->
datum_spec.crit_id
crit_obj: (n) ->
if n
datum_spec.crit_obj = n
datum_spec.crit_obj
cand_obj: (n) ->
if n
datum_spec.cand_obj = n
datum_spec.cand_obj
write_datum_to_storage: (args) ->
pndr.write_to_storage(self)
set_value: (v) ->
We set this here because valuetype.coerce_to_valuetype calls datum.value()
initial_value = datum_spec.value
datum_spec.value = v
final_value = self.crit_obj().crit_coerce_to_valuetype(self)
datum_spec.value = final_value
if is_defined(initial_value) and (initial_value isnt final_value)
FIXME push value to server
unless self.write_datum_to_storage()
self.cand_obj().dirty(true)
self.cand_obj().unsorted(true)
if self.get_valuetype().get_sort_onchange()
pndr.sort_candidates_if_unsorted()
value: -> # THIS IS THE GROUND OF THE VALUE CHAIN
if datum_spec.reactor
return datum_spec.reactor.get_value()
return datum_spec.value
input_element_id: ->
datum_spec.crit_id + "__" + datum_spec.cand_id + "__" + "input"
display_within: (n) ->
datum_spec.display_within = n if n
datum_spec.display_within
get_valuetype: ->
self.crit_obj().valuetype()
cell_being_edited: ->
retval = not not (pndr.is_spreadsheet_mode() and pndr.datum_being_edited is @)
return retval
update_datum_display: (args) =>
vt = self.get_valuetype()
if self.display_within()
edit_this_cell_only = self.cell_being_edited()
if pndr.being_edited() or edit_this_cell_only
self.display_within().innerHTML = self.get_editable_value()
inp = document.getElementById(self.input_element_id())
if inp
if edit_this_cell_only
inp.onblur = (evt) ->
console.log "onblur", evt
inp.onchange = pndr.make_cell_value_onchange_handler(self)
inp.focus()
else
inp.onchange = pndr.set_datum_value
inp.onblur = pndr.sort_candidates_if_unsorted
else
v = self.get_display_value()
self.display_within().innerHTML = (if (v isnt `undefined`) then v else "")
if pndr.is_spreadsheet_mode()
self.display_within().onclick = (evt) ->
self.spreadsheet_cell_onclick_handler(evt)
spreadsheet_cell_onclick_handler: (evt) ->
self.display_within().onclick = null # disable once it has been used
prior = pndr.datum_being_edited
pndr.datum_being_edited = @
if prior
prior.update_datum_display()
self.update_datum_display()
self
/////////////////////////////////////////////// CRITERION Note the use of crit_spec as a closure within self.
TODO refactor criterion, datum and candidate TODO https://bitbucket.org/smurp/libnoo/issues/186/ https://github.com/dustinboston/coffeescript-design-patterns#facade https://github.com/dustinboston/coffeescript-design-patterns#flyweight https://github.com/dustinboston/coffeescript-design-patterns#proxy
Problems:
Criterion_defaults: # TODO put on Criterion class but protect from writing? smaller_values_better: false default_order: +1 cells_visualizable: false class Criterion constructor: (crit) -> # crit is equivalent to the existing ‘crit_spec’ if not crit crit = {} crit.proto = Criterion_defaults @id: -> crit.id
criterion = (crit_spec) ->
crit_spec = {} unless crit_spec
crit_defaults =
sort_order: ‘DESC’, // vs ASC vs NULL
smaller_values_better: false
default_order: +1 # ie NO CHANGE FROM THE VALUETYPE DEFAULT ORDER
cells_visualizable: false
crit_spec.__proto__ = crit_defaults
crit_spec.associated_data = []
self =
spawn_datum: (args) ->
a_datum = datum(
cand_id: args.cand_id # TODO save cand_obj: directly
crit_id: self.id() # TODO save crit_obj: directly
value: ""
)
if crit_spec.formula
a_datum.reactor = self.interactor().spawn_reactor(a_datum, crit_spec.formula)
return a_datum
formula: (formula) ->
if formula?
crit_spec.formula = formula
return crit_spec.formula
interactor: (ntrctr) ->
if not ntrctr
crit_spec.interactor = ntrctr
return crit_spec.interactor
get_cmp: (args) ->
if (crit_spec.valuetype.cmp_function){
alert("using cmp_function");
return crit_spec.valuetype.cmp_function;
}
if crit_spec.valuetype
return crit_spec.valuetype.cmp
descending_cmp
default_order: (i) ->
crit_spec.default_order = i if is_defined(i)
crit_spec.default_order
cells_visualizable: (n) ->
crit_spec.cells_visualizable = n if n? # assign new value if present
crit_spec.cells_visualizable
add_crit_to_table: (args) ->
self.discover_valuetype()
self.make_crit_table_elements args
self.register_crit()
self.update_crit_visible()
valuetype_picker_id: (args) ->
self.id() + "__valuetype_picker"
valuetype_id: (n) ->
crit_spec.valuetype_id = n if n? # assign new value if present
crit_spec.valuetype_id
valuetype: (vt) ->
crit_spec.valuetype = vt if vt? # assign new value if present
crit_spec.valuetype
set_valuetype_by_xsd: (xsd_type) ->
crit_spec.valuetype = xsd_type_to_valuetype(xsd_type)
console.log crit_spec.valuetype
crit_spec.valuetype
draggable_thing: ->
crit_spec.draggable_thing
label: (label) ->
crit_spec.label = label if is_defined(label)
crit_spec.label
idx: (n) ->
crit_spec.row_idx = n if is_defined(n)
crit_spec.row_idx
getElementsByClassName: (class_name, tag_hint) ->
if crit_spec.tr.getElementsByClassName
crit_spec.tr.getElementsByClassName class_name
else
gEBCN crit_spec.tr, class_name, tag_hint
tr: (tr) ->
if tr
crit_spec.tr = tr
crit_spec.row_idx = tr.sectionRowIndex
ptw_vars.criteria_by_row_idx[crit_spec.row_idx] = self
crit_spec.tr
id: (n) ->
crit_spec.id = n if n # FIXME reregister everything when ID changes
crit_spec.id
id_of_html_elem: ->
"crit__" + self.id()
discover_crit_label: (args) ->
self.label self.tr().getElementsByClassName("criterionLabel")[0].innerHTML # TEST [0] is untested
pack_crit_for_saving: (args) ->
out =
label: self.discover_crit_label()
valuetype_id: self.valuetype_id()
default_order: self.default_order()
id: self.id()
out
discover_valuetype: (args) ->
a_vt = valuetype_factory.get(crit_spec.valuetype_id)
return unless a_vt
a_vt = valuetypes[‘plain’];
crit_spec.valuetype = a_vt
crit_display_value: (a_datum) ->
return crit_spec.valuetype.get_display_value(a_datum) if crit_spec.valuetype
""
crit_saveable_value: (a_datum) ->
return crit_spec.valuetype.get_saveable_value(a_datum) if crit_spec.valuetype
""
crit_sortable_value: (a_datum) ->
return crit_spec.valuetype.get_sortable_value(a_datum) if crit_spec.valuetype
""
crit_editable_value: (a_datum) ->
return crit_spec.valuetype.get_editable_value(a_datum) if crit_spec.valuetype
""
crit_coerce_to_valuetype: (a_datum) ->
crit_spec.valuetype.vt_coerce_to_valuetype a_datum if crit_spec.valuetype
is_hidden: (args) ->
$(self.crit_label_box()).is ":hidden"
crit_label_box: ->
r = crit_spec.tr.lastChild
r
crit_arrow_box: ->
This is tricky! The arrow_box for a criterion is the td.arrow_box of the row below the one containing the crition label. That is, a criterion’s arrow_box is the arrow below the criterion name, which is neccessarily in the row (tr) below the criterion name. This works even for the bottom criterion because that row is followed by the row containing the windowShade, which also has a td.arrow_box as its first element.
console.log "nextSibling of ", crit_spec.tr.rowIndex, crit_spec.tr, "is", crit_spec.tr.nextSibling and crit_spec.tr.nextSibling.rowIndex, crit_spec.tr.nextSibling if window.DEBUG_SHADING
td = crit_spec.tr.nextSibling.firstChild
for child in crit_spec.tr.nextSibling.children
if $(child).hasClass('arrow_box')
return child
$(td).attr(‘style’, “background:red”)
console.log "a child with class .arrow_box was expected in",crit_spec.tr.nextSibling
debugger
console.log(“#TD in TR”,crit_spec.tr.children.length,crit_spec.tr.id);
hide: (args) ->
$(self.crit_label_box()).hide()
arrow = self.crit_arrow_box()
console.log "hiding arrow in row " + arrow.parentNode.rowIndex + " labelled: \"" + arrow.parentNode.innerText + "\"" if window.DEBUG_SHADING
$(arrow).hide()
if not $(arrow).is(‘:hidden’) debugger
if (crit_spec.tr.rowIndex == 1){
// hide the arrow_box beside the controls
$(ptw_vars.wgt_controls.firstChild).hide();
if (window.DEBUG_SHADING)
console.log("arrowbox beside controls hidden: ",$(ptw_vars.wgt_controls.firstChild).is(':hidden'));
}
self.hide_column()
hide_column: (args) ->
self.for_each_cell_in_column_do "hide"
show: (args) ->
console.log(self,”show()”);
$(self.crit_label_box()).show()
$(self.crit_arrow_box()).show()
self.show_column()
show_column: (args) ->
self.for_each_cell_in_column_do "show"
for_each_cell_in_column_do: (func_name) ->
col_idx = crit_spec.row_idx
idx = 0
while idx < ptw_vars.candidates_by_row_idx.length
a_cand_row = ptw_vars.candidate_rows.children[idx]
$(a_cand_row.children[col_idx])[func_name]() if a_cand_row
idx++
make_crit_table_elements: (args) ->
args = {} unless args
FIXME when the sort controls get added this will need work do not insert at the end, that is where the controls are args.row_idx = ptw_vars.wgt_table.tHead.childElementCount - 1; // fails on IE
args.row_idx = ptw_vars.criteria_by_row_idx.length if args.row_idx is `undefined`
var tr = ptw_vars.wgt_table.tHead.insertRow(args.row_idx);
tr = ptw_vars.criterion_rows.insertRow(args.row_idx)
if (! tr.getElementsByClassName){tr.getElementsByClassName = cstmGetElementsByClassNameExt2;}
tr.id = self.id_of_html_elem()
tr.setAttribute "class", "criterionRow" # " fa arrows-v"
td_1 = tr.insertCell(0)
elem_to_drag = td_1
td_1.setAttribute "class", "criterionControl"
if ptw_vars.have_special_grab_grip_cell
td_2 = tr.insertCell(-1)
elem_to_drag = td_2
td_2.setAttribute “class”, “fa arrows-v” # Why does this not work?
elem_to_drag.ondragend = pndr.drop_criterion
crit_label_span = document.createElement("span")
crit_label_span.contentEditable = true
td_1.appendChild crit_label_span
crit_label_span.setAttribute "class", "criterionLabel contentEditableInEditMode"
crit_label_span.onblur = pndr.onblur_criterion_label_handler
crit_label_span.onfocus = pndr.onfocus_criterion_label_handler
if ptw_vars.display_criterion_default_order_control
ord_butt = document.createElement("span")
ord_butt.setAttribute "class", "criterionOrderButton"
“criterionOrderButton editControl contentAlterableInEditMode”);
$(ord_butt).click pndr.reverse_criterion_default_order_handler
td_1.appendChild ord_butt
if ptw_vars.display_criterion_valuetype_control
crit_valuetypeid_span = document.createElement("span")
td_1.appendChild crit_valuetypeid_span
crit_valuetypeid_span.setAttribute "class", "valuetypeId contentAlterableInEditMode"
crit_valuetypeid_span.onclick = (if ptw_vars.being_edited then pndr.display_criterion_valuetype_selector else null)
crit_spec.draggable_thing = td_1
crit_spec.draggable_thing.draggable = true # FIXME see set_visibility_of_controls
crit_spec.tr = tr # so we can reach the tr from the crit_obj
register_crit: (args) ->
crit_spec.row_idx = crit_spec.tr.sectionRowIndex
ptw_vars.criteria_by_row_idx[crit_spec.row_idx] = self
data_will_be_lost_if_valuetype_changes_to: (evt) ->
current_valuetype = self.valuetype()
proposed_valuetype = pndr.get_valuetype_by_id(evt.target.value)
console.log "data_will_be_lost_if_valuetype_changes_to:", current_valuetype, current_valuetype.id(), proposed_valuetype.id(), evt.target.value
return false if current_valuetype is proposed_valuetype
not current_valuetype.can_be_converted_without_loss_to(proposed_valuetype)
remember_datum: (a_datum) ->
crit_spec.associated_data.push a_datum
forget_datum: (a_datum) ->
io = crit_spec.associated_data.indexOf(a_datum)
crit_spec.associated_data.unshift io if io > -1
num_of_candidates_with_non_defaulted_data: (args) ->
crit_spec.associated_data.length
display_valuetype_selector: (args) ->
self.getElementsByClassName("valuetypeId")[0].innerHTML = valuetype_picker(
value: crit_spec.valuetype_id
criterion: self
)
document.getElementById(self.valuetype_picker_id()).onchange = pndr.set_criterion_valuetype_handler
document.getElementById(self.valuetype_picker_id()).onblur = pndr.set_criterion_valuetype_handler
update_crit_visible: (args) ->
self.getElementsByClassName("criterionLabel")[0].innerHTML = crit_spec.label
if crit_spec.valuetype_id
show_idx = (if false then " " + crit_spec.row_idx + " " else "")
self.getElementsByClassName("valuetypeId")[0].innerHTML = crit_spec.valuetype_id if ptw_vars.display_criterion_valuetype_control
if ptw_vars.display_criterion_default_order_control
if self.default_order() is 1
self.getElementsByClassName("criterionOrderButton")[0].innerHTML = ptw_vars.down_arrow
else
self.getElementsByClassName("criterionOrderButton")[0].innerHTML = ptw_vars.up_arrow
else
self.display_valuetype_selector()
ensure_arrow_cell_beside: (args) ->
if crit_spec.tr.children.length is 1
pndr.add_arrow_cell_to target: crit_spec.tr
return
increase_height_of_arrow: (args) ->
crit_spec.tr.children[0].setAttribute "rowspan", pndr.get_num_criteria() - crit_spec.row_idx + 1
push_down: (args) ->
self.register_crit()
self.ensure_arrow_cell_beside()
self.increase_height_of_arrow()
self.update_colspan()
self.update_crit_visible()
update_colspan: (args) ->
lbl_cell = crit_spec.tr.children[1]
if lbl_cell
lbl_cell.setAttribute "colspan", pndr.get_num_columns() - crit_spec.row_idx
self
/////////////////////////////////////////////// VALUETYPE
valuetype = (vtspec) ->
vtspec = {} unless vtspec
on_obj_put_proto vtspec,
can_be_converted_to_from_any_valuetype: false
sort_onchange: true
descending_cmp: descending_cmp, ascending_cmp: ascending_cmp,
cmp: descending_cmp
self =
id: (id) ->
write once, not changeable
vtspec.id = id if is_defined(id) and is_undefined(vtspec.id)
vtspec.id
cmp: (a_datum, b_datum) ->
return vtspec.cmp(a_datum, b_datum)
the_display_value: (a_datum) ->
if vtspec.display_value_func
return vtspec.display_value_func(a_datum.value())
if vtspec.value_to_display
return vtspec.value_to_display[a_datum.value()]
return a_datum.value()
get_sort_onchange: ->
vtspec.sort_onchange
can_be_converted_without_loss_to: (another_valuetype) ->
vtspec.can_be_converted_to_from_any_valuetype
get_select_input: (a_datum) ->
k = undefined
v = a_datum.value()
iei = a_datum.input_element_id()
out = "<select id=\"" + iei + "\" name=\"" + iei + "\">\n"
out += "<option value=\"\"></option>\n"
for k of vtspec.value_to_display
sel = (if k is v + "" then " selected" else "")
out += "<option" + sel + " value=\"" + k + "\">" + vtspec.value_to_display[k] + "</option>\n"
out += "</select>\n"
out
get_editable_value: (a_datum) ->
if vtspec.value_to_display
return self.get_select_input(a_datum)
v = self.the_display_value(a_datum)
v = (if v then v else "")
v = v.replace(/\"/, "\"").replace(/\</, "<").replace(/\>/, ">") if vtspec.escape_to_edit
if vtspec.html_input
retval = "<input "
retval += "name=\"" + a_datum.input_element_id() + "\" "
retval += "id=\"" + a_datum.input_element_id() + "\" "
for key of vtspec.html_input
val = vtspec.html_input[key]
val = v if key is "value"
if key is "value" and v is `undefined`
retval += "value=\"" + v + "\" "
else
retval += key
retval += "=\"" + val + "\" " if typeof val isnt "undefined"
retval += "/>"
retval
else
if vtspec.edit_in_textarea
self.wrap_in_prefix_postfix "<textarea " + "name=\"" + a_datum.input_element_id() + "\"" + "id=\"" + a_datum.input_element_id() + "\"" + ">" + v + "</textarea>"
else
self.wrap_in_prefix_postfix "<input type=\"text\" " + "name=\"" + a_datum.input_element_id() + "\"" + "id=\"" + a_datum.input_element_id() + "\"" + " size=\"10\" value=\"" + v + "\"/>"
wrap_in_prefix_postfix: (s) ->
prefix = vtspec.prefix or ""
postfix = vtspec.postfix or ""
if s
return prefix + ((if s then s else "")) + postfix
""
wrap_in_aligner: (s) ->
return "<div align=\"" + vtspec.align + "\">" + s + "</div>" if vtspec.align
s
get_display_value: (args) ->
self.wrap_in_aligner self.wrap_in_prefix_postfix(self.the_display_value(args))
get_saveable_value: (a_datum) ->
retval = undefined
if vtspec.get_saveable_value
retval = vtspec.get_saveable_value(a_datum)
else
retval = a_datum.value()
if vtspec.get_saveable_value_regexp
m = ("" + retval).match(vtspec.get_saveable_value_regexp)
get first non-empty match
i = 0
while i < m.length
if m[i]
retval = m[i]
break
i++
console.log(‘vtspec’,m,retval);
retval = vtspec.caster(retval) if vtspec.caster
retval
get_sortable_value: (a_datum) ->
retval = undefined
if vtspec.get_sortable_value
retval = vtspec.get_sortable_value(a_datum)
else
retval = vtspec.get_saveable_value(a_datum)
retval
vt_coerce_to_valuetype: (a_datum) ->
v = a_datum.value()
if vtspec.value_to_saveable
if vtspec.value_to_saveable[v] isnt `undefined`
return vtspec.value_to_saveable[v]
if vtspec.vt_coerce_to_valuetype
return vtspec.vt_coerce_to_valuetype(a_datum)
return a_datum.value()
self
see duplication in app.js
choosable_agent_types =
self: "self"
workgroup: "workgroup"
family: "family"
friends: "friends"
public: "public"
add_commas = (nStr) ->
nStr += ""
x = nStr.split(".")
x1 = x[0]
x2 = (if x.length > 1 then "." + x[1] else "")
rgx = /(\d+)(\d{3})/
x1 = x1.replace(rgx, "$1" + "," + "$2") while rgx.test(x1)
x1 + x2
remove_commas = (nStr) ->
nStr = "" + nStr
parseFloat (nStr).replace(/\,/g, "")
remove_dollars = (nStr) ->
nStr = "" + nStr
parseFloat (nStr).replace(/\$/g, "")
good_number = (num) ->
(if isNaN(num) then `undefined` else num)
primitive_valuetypes =
agent_type: valuetype(
value_to_display: choosable_agent_types
display_to_value: choosable_agent_types
)
boolean: valuetype(
value_to_display:
true: unicod.big_check
false: unicod.big_X
value_to_saveable:
true: true
false: false
0: true
1: false
)
date: valuetype(
html_input:
type: "date"
get_saveable_value: (a_datum) ->
d = new Date(a_datum.value())
d.toJSON().substr(0, 10)
)
datetime: valuetype(
html_input:
type: "datetime-local"
value: undefined # ie get the value from the datum
display_value_func: (a_datum) ->
Convert a_datum from whatever TZ it is in to local time and remove all mention of TZ. eg 2016-07-01T12:00:00Z ==> 2016-07-01T06:00:00 (for MDT local)
if a_datum is a_datum.substr(0,19)
console.log("assuming #{a_datum} is Zulu time")
TODO expose a warning mark in the UI that zulu time is assumed
localize_iso8601(a_datum)
get_saveable_value: (a_datum) ->
console.log(a_datum, "is being saved incorrectly")
d = new Date(a_datum + 'Z')
d.toJSON()
)
return ‘Date(‘+d.UTC()+’)’;
dollars: valuetype(
prefix: "$"
get_saveable_value_regexp: /(\d*\.?\d*)/g
align: "right"
display_value_func: add_commas
vt_coerce_to_valuetype: (a_datum) ->
good_number parseFloat(remove_dollars(remove_commas(a_datum.value())))
)
five_stars: valuetype(
align: "left"
value_to_display:
0: ‘’,
1: "★"
2: "★★"
3: "★★★"
4: "★★★★"
5: "★★★★★"
value_to_saveable:
5: 5
4: 4
3: 3
2: 2
1: 1
0: 0
"": 0
)
html_snippet: valuetype
escape_to_edit: true
edit_in_textarea: true
integer: valuetype
align: "right"
display_value_func: add_commas
vt_coerce_to_valuetype: (a_datum) ->
good_number parseInt(remove_commas(a_datum.value()), 10)
letter_grade: valuetype(
cmp: ascending_cmp
value_to_display:
A: "Ⓐ"
B: "Ⓑ"
C: "Ⓒ"
D: "Ⓓ"
E: "Ⓔ"
F: "Ⓕ"
references: ["http://www.iam.uni-bonn.de/~alt/html/unicode_170.html"]
)
float: valuetype
align: "right"
display_value_func: add_commas
get_saveable_value: (a_datum) ->
good_number parseFloat(a_datum.value())
vt_coerce_to_valuetype: (a_datum) ->
good_number parseFloat(a_datum.value())
plain: valuetype
can_be_converted_to_from_any_valuetype: true
duration: valuetype() # http://www.datypic.com/sc/xsd/t-xsd_duration.html
timestamp: valuetype
get_saveable_value: (a_datum) ->
d = new Date(a_datum.value())
d.toJSON()
display_value_func: (nStr) ->
if typeof nStr is 'string'
nStr.replace(/T/,' ')
else
nStr
return ‘Date(‘+d.UTC()+’)’
foreign_key: valuetype
username: valuetype(cmp: (a, b) ->
current_user = pndr.get_account_names()
if true
return 0 if a is b
return -1 if a in current_user
return 1 if b in current_user
descending_cmp a, b
else descending_cmp a, b
)
zero_to_one: valuetype(
align: "right"
type: "number"
sort_onchange: false
caster: parseFloat
html_input:
type: "range"
min: 0
max: 1
step: "0.01"
value: "0"
)
valuetype_factory_f = (vtf_spec) ->
The valuetype_factory is a registry and generator of valuetypes. Some valuetypes are simple hardcoded things (at the moment!) but others might be elaborate gizmos which are self-referential to the current ponder or indeed they might rely on the contents of other ponders.
vtf_spec = vtf_spec or {}
vtf_spec.__proto__ = {}
vtf_spec.valuetypes_by_id = {}
self =
ids: (args) ->
out = []
for i of vtf_spec.valuetypes_by_id
out.push i
out
register_vt: (args) ->
vbi = vtf_spec.valuetypes_by_id
vbi[args.id] = args.vt
args.vt.id args.id
get: (vt_id) ->
vtf_spec.valuetypes_by_id[vt_id]
register_primitives: (args) ->
for vt_id of primitive_valuetypes
if primitive_valuetypes.hasOwnProperty(vt_id)
vt = primitive_valuetypes[vt_id]
self.register_vt
id: vt_id
vt: vt
self.register_primitives()
self
valuetype_factory = valuetype_factory_f()
valuetype_picker = (args) ->
v = (if args.value then " value=\"" + args.value + "\"" else "")
pre = ptw_vars.table_id + "__"
onchange = ""
picker_id = args.criterion.valuetype_picker_id()
out = "<select id=\"" + picker_id + "\" name=\"" + v + "\">\n"
out += "<option value=\"\"></option>\n"
vt_ids = valuetype_factory.ids()
for i of vt_ids
k = vt_ids[i]
sel = (if k is args.value + "" then " selected" else "")
out += "<option" + sel + " value=\"" + k + "\">" + k + "</option>\n"
out += "</select>\n"
out
qnames =
wordnet: "http://wordnetweb.princeton.edu/perl/webwn?s="
wiki: "http://en.wikipedia.org/wiki/"
that =
expand_qname: (input) ->
get_next_criterion_id: (args) ->
pndr.generate_id()
get_next_candidate_id: (args) ->
pndr.generate_id()
is_hidden: ->
ptw_vars.wgt_table.style.display is "none"
hide: ->
ptw_vars.wgt_table.style.display = "none"
show: ->
ptw_vars.wgt_table.style.display = "block"
toggle_display: ->
if pndr.is_hidden()
pndr.show()
else
pndr.hide()
update_windowShadeLabel: (args) ->
num = ptw_vars.num_crit_shaded
if num > 0
ptw_vars.windowShadeLabel.innerHTML = Math.floor(num) + " more criteria"
else
ptw_vars.windowShadeLabel.innerHTML = ""
reshade: (args) ->
console.log(“reshade(): num_crit_shaded =”,ptw_vars.num_crit_shaded, “num_crit_shaded_this_drag =”,ptw_vars.num_crit_shaded_this_drag); visit each crit from the end if it should be hidden and it is not, hide it if it should not be hidden and it is, show it if it should be shown and it is, break
num_to_shade = ptw_vars.num_crit_shaded
num_crit = ptw_vars.criteria_by_row_idx.length
num_shaded_so_far = 0
count back from the end of the criteria
crit_idx = num_crit - 1
while crit_idx > -1
shade_this_crit = num_shaded_so_far < num_to_shade
crit = ptw_vars.criteria_by_row_idx[crit_idx]
unless crit
console.log "crit not found, skipping", crit_idx if window.DEBUG_SHADING
continue
console.log "--------", crit_idx if window.DEBUG_SHADING
if shade_this_crit
unless crit.is_hidden()
console.log shade_this_crit, " A it is not hidden but it should be, so crit.hide()", crit.id(), crit_idx if window.DEBUG_SHADING
crit.hide()
pndr.adjust_tds_widenedByUnshadedCritCount(-1)
else it IS hidden so we do not need to hide it again
else
console.log "it should NOT be hidden" if window.DEBUG_SHADING
it should NOT be hidden
if crit.is_hidden()
console.log "but it IS, so show it" if window.DEBUG_SHADING
but it IS, so show it
console.log shade_this_crit, " B it is hidden but should not be, so crit.show()", crit.id, crit_idx if window.DEBUG_SHADING
crit.show()
pndr.adjust_tds_widenedByUnshadedCritCount(+1)
else
and it IS NOT HIDDEN, presumably like higher criteria, so…
console.log shade_this_crit, " C it is not hidden, and should not be, so skip", crit.id, crit_idx if window.DEBUG_SHADING
num_shaded_so_far++
crit_idx--
navigate_to_ponder: (pndr_id) ->
params =
pndr_id: pndr_id
origin_url: Ponderate.canonical_origin_url
show_edit_button: true
being_edited: true
add_current_page_as_candidate: true
Ponderate.op_queue__push params
pndr.hide()
Ponderate.insert_a_ponder params
pndr.empty_the_frame(); Ponderate.op_queue__drain();
return
choose_ponder_to_add_candidate_to_handler: (evt) ->
a .span .td .tr
a_row = evt.target.parentNode.parentNode.parentNode
a_cand = ptw_vars.candidates_by_row_idx[a_row.sectionRowIndex]
alert(a_cand.label()+” chosen!”); a_cand.get_ponder_id_from_url();
pndr.navigate_to_ponder a_cand.get_ponder_id_from_url()
del_candidate_handler: (evt) ->
button.td .tr
a_row = evt.target.parentNode.parentNode
a_cand = ptw_vars.candidates_by_row_idx[a_row.sectionRowIndex]
if confirm("delete " + a_cand.label() + "?")
pndr.del_candidate a_cand
false
edit_candidate_link_handler: (evt) ->
button.td .tr
a_row = evt.target.parentNode.parentNode
a_cand = ptw_vars.candidates_by_row_idx[a_row.sectionRowIndex]
args =
label: a_cand.label()
url: a_cand.url()
args = pndr.prompt_for_candidate_url(args)
unless args.url
a_cand.delete_url()
else
a_cand.url args.url
a_cand.update_cand_visible()
true
reverse_criterion_default_order_handler: (evt) ->
console.log(‘rcdoh()’);
a_row = evt.target.parentNode.parentNode
a_crit = ptw_vars.criteria_by_row_idx[a_row.sectionRowIndex]
a_crit.default_order -1 * a_crit.default_order()
a_crit.update_crit_visible()
pndr.sort_candidates_by_criteria()
onblur_candidate_label_handler: (evt) ->
a_row = evt.target.parentNode.parentNode
a_cand = ptw_vars.candidates_by_row_idx[a_row.sectionRowIndex]
target = get_event_target(evt)
unvetted_new_label = target.innerText or target.textContent
unless unvetted_new_label is a_cand.label()
if has_value(unvetted_new_label) and (unvetted_new_label isnt "")
a_cand.label unvetted_new_label
a_cand.update_cand_visible()
return true
false
onblur_criterion_label_handler: (evt) ->
a_row = evt.target.parentNode.parentNode
a_crit = ptw_vars.criteria_by_row_idx[a_row.sectionRowIndex]
target = get_event_target(evt)
unvetted_new_label = target.innerText or target.textContent
console.log(‘saving any changes to label of ‘+a_crit.label());
a_crit.draggable_thing().draggable = true # toggled off in onfocus_criterion_label_handler
unless (unvetted_new_label) is a_crit.label()
if has_value(unvetted_new_label) and (unvetted_new_label isnt "")
a_crit.label unvetted_new_label
a_crit.update_crit_visible()
return true
false
onfocus_criterion_label_handler: (evt) ->
Turn off draggable so that editing can work properly, this is matched in onblur_criterion_label_handler by the restoration of draggability.
a_row = evt.target.parentNode.parentNode
a_crit = ptw_vars.criteria_by_row_idx[a_row.sectionRowIndex]
toggled on in onfocus_criterion_label_handler
a_crit.draggable_thing().draggable = false
evt.target.focus()
del_candidate: (a_cand) ->
alert(‘deleting ‘+a_cand.label());
a_cand.remove()
add_candidate_handler: (evt) ->
if ptw_vars.add_candidate_url
window.location.assign ptw_vars.add_candidate_url
true
else
pndr.has_unsaved_changes true
pndr.add_candidate row_idx: 0
reindex_candidates_by_row: (args) ->
for id of ptw_vars.candidates_by_their_id
if ptw_vars.candidates_by_their_id.hasOwnProperty(id)
cand = ptw_vars.candidates_by_their_id[id]
cand.register_cand()
FIXME THIS IS NOT IN USE
reindex_criteria_by_row: (args) ->
for id of ptw_vars.criteria_by_their_id
if ptw_vars.criteria_by_their_id.hasOwnProperty(id)
crit = ptw_vars.criteria_by_their_id[id]
crit.register_crit()
prompt_for_candidate_url: (args) ->
prmpt = (if is_undefined(args.url) then "" else args.url)
retval = prompt("URL for '" + args.label + "'", prmpt)
args.url = retval if retval isnt null
delete args.url if is_undefined(args.url)
args
add_candidate: (args) ->
console.log(“adding”,args);
args = {} unless args
args.id = pndr.get_next_candidate_id() unless args.id
if ptw_vars.candidates_by_their_id[args.id]
return null
if not args.label or args.vet_label
args.label = prompt("Enter label for new candidate", (if args.label then args.label else ""))
return null unless args.label
args = pndr.prompt_for_candidate_url(args) if not args.url or args.vet_url
ensure_uniqueness = true
if ensure_uniqueness
found_by_label = pndr.find_candidate_by_label[args.label]
found_by_url = pndr.find_candidate_by_url[args.url]
if found_by_label or found_by_url
msg = (if found_by_label then "a candidate of that name already exists" else "a candidate with that url already exists")
scroll to found and hilight it
pndr.show_message msg
found_thing = found_by_label or found_by_url
console.log(“tr:”,found_thing.tr);
c = candidate(args)
ptw_vars.candidates_by_their_id[c.id()] = c
c.add_cand_to_table args
pndr.reindex_candidates_by_row() if c.idx() is 0
c
find_candidate_by_label: (label) ->
if not ptw_vars.candidates_by_label and ptw_vars.candidates_by_row_idx.length > 0
pndr.reindex_candidates_by_row()
ptw_vars.candidates_by_label[label]
find_candidate_by_url: (url) ->
if not ptw_vars.candidates_by_their_id and ptw_vars.candidates_by_row_idx.length > 0
pndr.reindex_candidates_by_row()
ptw_vars.candidates_by_their_id[url]
add_criterion_handler: (args) ->
if ptw_vars.add_criterion_url
window.location.assign ptw_vars.add_criterion_url
true
else
pndr.has_unsaved_changes true
pndr.add_criterion args
add_criterion: (args) ->
args = {} unless args
args.id = pndr.get_next_criterion_id() unless args.id
unless args.label
args.label = prompt("Enter label for new criterion: eg. Happiness")
return null unless args.label
c = criterion(args)
ptw_vars.criteria_by_their_id[c.id()] = c
c.add_crit_to_table()
pndr.push_down_criteria except: c
pndr.add_column_to_candidates crit_obj: c
pndr.adjust_tds_widenedByCritCount +1
c
get_criterion_by_id: (crit_id) ->
ptw_vars.criteria_by_their_id[crit_id]
get_criterion_by_idx: (crit_idx) ->
ptw_vars.criteria_by_row_idx[crit_idx]
get_candidate_by_id: (cand_id) ->
ptw_vars.candidates_by_their_id[cand_id]
get_datum_by_cand_id_and_crit_id: (cand_id, crit_id) ->
cand = pndr.get_candidate_by_id(cand_id)
if cand?
return cand.get_datum_by_crit_id(crit_id)
return
getElementsByClassName: (class_name, tag_hint) ->
if ptw_vars.wgt_frame.getElementsByClassName
ptw_vars.wgt_frame.getElementsByClassName class_name
else
gEBCN ptw_vars.wgt_frame, class_name, tag_hint
getElementById: (id) ->
ptw_vars.wgt_table.getElementsById id
adjust_tds_widenedByCritCount: (incr) ->
Ideally a selector for class widenedByCritCount would pick the things to have their colspans incremented or decremented
widen_these = pndr.getElementsByClassName("widenedByCritCount")
for i of widen_these
a_td = widen_these[i]
a_td.colSpan += incr
pndr.adjust_tds_widenedByUnshadedCritCount(incr)
adjust_tds_widenedByUnshadedCritCount: (incr) ->
Ideally a selector for class widenedByCritCount would pick the things to have their colspans incremented or decremented
widen_these = pndr.getElementsByClassName("widenedByUnshadedCritCount")
for i of widen_these
a_td = widen_these[i]
a_td.colSpan += incr
add_datum: (args) ->
if typeof (args) is typeof ([])
orig_args = args
args =
cand_id: args[0]
crit_id: args[1]
value: args[2]
the_cand = ptw_vars.candidates_by_their_id[args.cand_id]
unless the_cand
console.log "candidate not found for datum:", args
return
the_datum = datum(args)
the_cand.add_datum_to_candidate the_datum
the_crit = ptw_vars.criteria_by_their_id[args.crit_id]
if the_crit
the_crit.remember_datum the_datum
else
console.log "criterion not found for datum:", args
TODO scan the candidate for impact of new datum on any formulae???
set_some_option: (evt) ->
update ptw_vars.readable_by from the select
ptw_vars[evt.srcElement.name] = evt.srcElement.value
dump_criteria_positions: (say) ->
console.log(“============” + “\n”+say);
for i of ptw_vars.criteria_by_row_idx
crit_obj = ptw_vars.criteria_by_row_idx[i]
console.log " ", crit_obj.label(), "sectionRowIndex", crit_obj.tr().sectionRowIndex + " i=" + i
move_criterion_to_index: (movee, dest_index) ->
pndr.dump_criteria_positions(‘before’);
earlier_tr = undefined
start_index = undefined
next_crit = undefined
next_earlier_tr = undefined
final_index = dest_index
i = undefined
if movee.idx() < final_index
console.log(“movee.idx() < final_index, ie %s < %s”, movee.idx(),final_index);
earlier_tr = movee.tr()
start_index = movee.idx()
next_crit = null
i = start_index
while i <= final_index
next_crit = ptw_vars.criteria_by_row_idx[i]
next_earlier_tr = next_crit.tr()
console.log(‘ bailing because crit not found for ‘+i);
continue unless next_crit
next_crit.tr earlier_tr
next_crit.update_crit_visible()
earlier_tr = next_earlier_tr
i++
movee.tr earlier_tr
movee.update_crit_visible()
if movee.idx() > final_index
console.log(“movee.idx() > final_index, ie %s > %s”, movee.idx(),final_index);
earlier_tr = movee.tr()
start_index = dest_index
final_index = movee.idx()
next_crit = null
i = final_index
while i >= start_index
next_crit = ptw_vars.criteria_by_row_idx[i]
next_earlier_tr = next_crit.tr()
console.log(‘ bailing because crit not found for ‘+i);
continue unless next_crit
next_crit.tr earlier_tr
next_crit.update_crit_visible()
earlier_tr = next_earlier_tr
i--
movee.tr earlier_tr
movee.update_crit_visible()
drop_criterion: (evt) ->
assumes the dragged elem was a td inside the tr with an id linking it to a criterion
ri = evt.srcElement.parentElement.rowIndex
crit_rows = ptw_vars.wgt_table.tHead.children
last_criterion_row_idx = crit_rows.length - 2
ni = pndr.find_new_index_among(evt, crit_rows, 0, last_criterion_row_idx)
console.log(“ni=”+ni+” ri=”+ri);
return false if is_undefined(ni) # see ref#6
dragged_crit = ptw_vars.criteria_by_row_idx[ri]
alert(“dropped on self”);
return false if ri is ni
unless ni is ri
pndr.move_criterion_to_index dragged_crit, ni
pndr.move_crit_data_from_to_ dragged_crit, ri, ni
alert(ptw_vars.criteria_by_row_idx[ni].label());
pndr.sort_candidates_by_criteria()
true
move_crit_data_from_to_: (moved_crit, from_idx, to_idx) ->
i = 0
while i < ptw_vars.candidates_by_row_idx.length
ptw_vars.candidates_by_row_idx[i].move_crit_datum_from_to_ moved_crit, from_idx, to_idx
i++
find_new_index_among: (evt, rows, first_idx, last_idx) ->
diff = document.body.scrollTop - document.body.clientTop
currentY = evt.clientY - diff
retval = undefined
row_idx = first_idx
while row_idx <= last_idx
row = rows[row_idx]
row_top = row.offsetTop + row.offsetParent.offsetTop + row.offsetHeight
row_bot = row_top + row.offsetHeight
console.log(“for row %s is %s <= %s <= %s?”, row_idx,row_top,currentY,row_bot);
return 0 if currentY < row_top
if currentY >= row_top and currentY <= row_bot
console.log(“yes!!”); console.log(evt,first_idx,last_idx,” ==> “,row_idx);
retval = Math.max(0, row_idx - 1)
break
row_idx++
retval = Math.max(row_idx - 1, 0) unless is_defined(retval)
retval = Math.min(retval, pndr.get_num_crit_unshaded() - 1)
retval
set_editing: (evt) ->
ptw_vars.being_edited = ((if evt.srcElement then evt.srcElement else evt.target)).checked
pndr.update_all_data_display()
pndr.set_visibility_of_controls() #ptw_vars.being_edited);
pndr.sort_candidates_by_criteria() unless ptw_vars.being_edited
install_stylesheet: (args) ->
http://www.howtocreate.co.uk/tutorials/javascript/domcss
http://dev.opera.com/articles/view/dynamic-style-css-javascript/ Not working great on IE
sheet = document.createElement("style")
ptw_vars.dynamic_stylesheet = sheet
ptw_vars.wgt_table.parentNode.insertBefore sheet, ptw_vars.wgt_table
pndr.insert_dynamic_stylesheet_rule [".authorizedUsersOnly", "{display:none;}"]
insert_dynamic_stylesheet_rule__IE_version: (rule) ->
dss = ptw_vars.dynamic_stylesheet.styleSheet
dss.addRule rule[0], rule[1], dss.rules.length
alert(rule);
insert_dynamic_stylesheet_rule__standard_version: (rule) ->
dssheet = ptw_vars.dynamic_stylesheet.sheet
dssheet.insertRule rule[0] + " " + rule[1], dssheet.cssRules.length
insert_dynamic_stylesheet_rule: (rule) ->
dss = ptw_vars.dynamic_stylesheet
if dss.sheet
pndr.insert_dynamic_stylesheet_rule__standard_version rule
IE
else pndr.insert_dynamic_stylesheet_rule__IE_version rule if dss.styleSheet
containing_frame: ->
ptw_vars.wgt_frame
make_caption_draggable_and_editable: ->
$(ptw_vars.caption_elem).click(); console.log “make_caption_draggable_and_editable()”
try
$(ptw_vars.wgt_frame).draggable(handle: ptw_vars.caption_elem).click(->
$(ptw_vars.wgt_frame).draggable disabled: false
).dblclick ->
$(ptw_vars.wgt_frame).draggable disabled: true
catch e
throw ("patched jquery-ui expects \"Ponderate.jQuery = jQuery\" for embed.js")
$(pndr.containing_frame()).draggable({handle:ptw_vars.caption_elem}); console.log(‘/make_caption_draggable_and_editable()’);
widget: ->
ptw_vars.wgt_table
set_style_on_widget_with: (rules) ->
style = pndr.transform_rules_to_string(rules)
console.log(“setting style on widget to”,style); pndr.widget().setAttribute(‘style’,”{“+pndr.transform_rules_to_string(rules)+”}”);
pndr.widget().setAttribute "style", style
transform_rules_to_string: (rules) ->
def = ""
i = 0
while i < rules.length
rule = rules[i]
def += rule[0] + rule[1] + " "
i++
def
replace_style_in_containing_div_with: (rules) ->
container = pndr.containing_frame()
old_styles = pndr.getElementsByClassName("ptwDynamicStyle", "style")
osi = old_styles.length - 1
while osi > -1
os = old_styles[osi]
console.log(“removeChild”,os);
container.removeChild os if os
osi--
ss1 = document.createElement("style")
ss1.setAttribute "type", "text/css"
ss1.setAttribute "class", "ptwDynamicStyle"
def = pndr.transform_rules_to_string(rules)
container.insertBefore ss1, container.childNodes[0]
if ss1.styleSheet # IE
ss1.styleSheet.cssText = def
else
ss1.appendChild document.createTextNode(def)
replace_dynamic_stylesheet_with: (rules) ->
pndr.empty_dynamic_stylesheet()
i = undefined
dss = ptw_vars.dynamic_stylesheet
console.log(“dss:”,dss,”cssRules:”,dss.cssRules,”rules:”,dss.rules); console.log(dss,ptw_vars.dynamic_stylesheet);
if dss.sheet # the standard
i = 0
while i < rules.length
rule = rules[i]
pndr.insert_dynamic_stylesheet_rule__standard_version rule
i++
else if dss.styleSheet # IE
i = 0
while i < rules.length
pndr.insert_dynamic_stylesheet_rule__IE_version rules[i]
i++
else
pndr.submit_bug_report
method: "pndr.replace_dynamic_stylesheet_with"
problem: "browser lacks dss.sheet and dss.styleSheet, not standard and not IE"
severity: "user experience affected"
empty_dynamic_stylesheet: (args) ->
dss = ptw_vars.dynamic_stylesheet
if dss.sheet # the standard
dss.sheet.deleteRule 0 while dss.sheet.cssRules.length > 0
else if dss.styleSheet # IE
dss.styleSheet.removeRule 0 while dss.styleSheet.rules.length > 0
else
pndr.submit_bug_report
method: "pndr.empty_dynamic_stylesheet"
problem: "browser lacks dss.sheet and dss.styleSheet, not standard and not IE"
severity: "user experience affected"
set_disabled_of_stylesheet_by_name: (stylesheet_name, disabled) ->
i = 0
while i < document.styleSheets.length
ss = document.styleSheets[i]
alert(ss.title); console.log(ss); alert(ss.href);
if ss.title is stylesheet_name or (ss.href and ss.href.indexOf(stylesheet_name) > -1)
alert ss.title + " was " + ((if ss.disabled then "disabled" else "")) + " and now is " + ((if disabled then "disabled" else ""))
ss.disabled = disabled
i++
set_visibility_of_controls: (args) ->
console.log(ptw_vars.wgt_table); alert(“set_visibility_of_controls”);
i = undefined
dynamic_style = ""
if true or is_IE
editButtons = pndr.getElementsByClassName("editButton")
i = 0
while i < editButtons.length
editButtons[i].style.display = (if ptw_vars.show_edit_button then "inline" else "none")
i++
editButtons[i].style.cssText = ptw_vars.show_edit_button ? “”:display_none;
editControls = pndr.getElementsByClassName("editControl")
i = 0
while i < editControls.length
editControls[i].style.display = (if ptw_vars.being_edited then "" else "none")
i++
editControls[i].style.cssText = ptw_vars.being_edited ? “”:display_none;
else
rules = []
alert(“ptw_vars.being_edited:”+ptw_vars.being_edited+” ptw_vars.show_edit_button:”+ptw_vars.show_edit_button);
rules.push [".editControl", display_none] unless ptw_vars.being_edited
rules.push([“caption:before”,’{content:”NOT being_edited”;font-size:8px;}’]);
rules.push [".editButton", "{display:none;}"] unless ptw_vars.show_edit_button
rules.push([“caption:after”,’{content:”DO NOT show_edit_button”;font-size:8px;}’]);
pndr.replace_style_in_containing_div_with(rules);
pndr.set_style_on_widget_with rules
pndr.replace_dynamic_stylesheet_with(rules);
editables = pndr.getElementsByClassName("contentEditableInEditMode")
i = 0
while i < editables.length
editables[i].contentEditable = ptw_vars.being_edited
i++
alterables = pndr.getElementsByClassName("contentAlterableInEditMode")
i = 0
while i < alterables.length
if ptw_vars.being_edited
alterables[i].draggable = false
alterables[i].onclick = pndr.display_criterion_valuetype_selector;
else
alterables[i].onclick = null
i++
them = pndr.getElementsByClassName("valuetypeId")
i = 0
while i < them.length
if ptw_vars.being_edited
them[i].draggable = false
them[i].onclick = pndr.display_criterion_valuetype_selector
else
them[i].onclick = null
i++
update_all_data_display: (args) ->
i = undefined
for i of ptw_vars.candidates_by_row_idx
console.log(i);
ptw_vars.candidates_by_row_idx[i].update_candidate_display()
discover_pndr8_title: (args) ->
captions = ptw_vars.wgt_table.getElementsByTagName("caption")
pndr.pndr8_title captions[0].innerText or captions[0].textContent if captions
pndr.pndr8_title()
pndr8_title: (s) ->
if typeof (s) is typeof ("")
ptw_vars.pndr8_title = s
captions = ptw_vars.wgt_table.getElementsByTagName("caption")
if captions.length
console.log(“captions.innerText” , typeof captions.innerText);
if typeof captions[0].innerText isnt "undefined"
captions[0].innerText = s
else
captions[0].textContent = s
ptw_vars.pndr8_title
submit_bug_report: (report) ->
if ptw_vars.submitted_bugs.indexOf(report) is -1
ptw_vars.submitted_bugs.push report
report.platform = navigator.platform
report.userAgent = navigator.userAgent
report.location = window.location
pndr.send_generic_json_to_server JSON.stringify(report), "PUT", pndr.ensure_absolute_url("/bug_report/")
ensure_absolute_url: (path) ->
console.log "ORIGIN_URL", ptw_vars.origin_url
ptw_vars.origin_url = window.location.origin if typeof ptw_vars.origin_url is "undefined"
console.log "ORIGIN_URL", ptw_vars.origin_url, "FORCED"
resp = (if (path[0] is "/") then ptw_vars.origin_url + path else path)
resp
generate_id: (typ) ->
return "a_random_oid"
save_all: (evt) ->
out = {}
pndr.discover_pndr8_title()
t = pndr.pndr8_title()
if t isnt `undefined` and t isnt ""
out["name"] = t
else
out["name"] = "no name"
out["candidates"] = pndr.candidates_for_saving()
out["criteria"] = pndr.criteria_for_saving()
out["data"] = pndr.candidate_data_for_saving()
out["writeable_by"] = ptw_vars.writeable_by
out["readable_by"] = ptw_vars.readable_by
out["created_by"] = ptw_vars.created_by
json_to_save = JSON.stringify(out)
console.log json_to_save
verb = undefined
path = "/pndr8n"
if pndr.ponderation_id()
verb = "PUT" # there IS an ID, so we are saving
path += "/" + pndr.ponderation_id()
else
verb = "POST" # there IS NOT and ID, so we are creating
url = pndr.ensure_absolute_url(path)
console.log verb, url
pndr.send_json_to_server json_to_save, verb, url
get_session_id: ->
console.log(“get_session_id”,document.cookie);
document.cookie
if (ptw_vars.session_id){
console.log("get_session_id",document.cookie);
return ptw_vars.session_id;
}
return "no session_id";
send_json_to_server: (json_to_save, verb, url) ->
handler = ->
console.log(“readyState:”,AJAX.readyState,” status:”,AJAX.status, “ responseText:”,AJAX.responseText);
if AJAX.readyState is 4 and AJAX.status is 204
pndr.has_unsaved_changes false
var json = eval( AJAX.responseText +”;”);
else if AJAX.readyState is 4 and AJAX.status is 201 #
new_location = AJAX.responseText
the Location header should suffice, but XMLHttpRequest does not permit access to the headers, so new location in body of the response
window.location.assign new_location
else console.log "Status != 20x... status=" + AJAX.status if AJAX.readyState is 4 and (AJAX.status < 200 or AJAX.status > 299)
console.log AJAX.status, AJAX.statusText, AJAX if AJAX.readyState is 4
AJAX = pndr.createXMLHttpRequest()
show = ->
AJAX.onreadystatechange = handler
AJAX.open verb, url
AJAX.withCredentials = "true"
console.log "AJAX.open", verb, url
AJAX.setRequestHeader "Content-type", "application/json"
AJAX.withCredentials = "true" # can not happen earlier
AJAX.send json_to_save
show()
send_generic_json_to_server: (json_to_save, verb, url) ->
handler = ->
if AJAX.readyState is 4 and AJAX.status is 200 # OK
console.log AJAX.responseText
else if AJAX.readyState is 4 or AJAX.status is 204 # No Content
console.log AJAX.responseText
else if AJAX.readyState is 4 and AJAX.status is 201 # Created
new_location = AJAX.responseText
the Location header should suffice, but XMLHttpRequest does not permit access to the headers, so new location in body of the response
window.location.assign new_location
else alert "Status != 20x... status=" + AJAX.status if AJAX.readyState is 4 and (AJAX.status < 200 or AJAX.status > 299)
console.log AJAX.status, AJAX.statusText, AJAX if AJAX.readyState is 4
AJAX = pndr.createXMLHttpRequest()
show = ->
AJAX.onreadystatechange = handler
AJAX.open verb, url
AJAX.setRequestHeader "Content-type", "application/json"
AJAX.withCredentials = "true" # can not happen earlier
AJAX.send json_to_save
show()
make_absolute_url: (url) ->
return pndr.get_ponderate_origin_url() + url if url[0] is "/"
url
fill_widget_with_json_from_url: (args) ->
verb = "GET"
json_to_send = ""
resp_json = undefined
url = args.src
handler = ->
try {
if AJAX.readyState is 4 and AJAX.status is 200 # OK
console.log(AJAX.responseText); eval(“resp_json = “+ AJAX.responseText+”;”);
args.ponderspec = JSON.parse(AJAX.responseText)
pndr.document_write_widget()
pndr.fill_widget_from_ponderspec args
pndr.sort_candidates_by_criteria args
pndr.set_visibility_of_controls() # TRIAL
console.log AJAX.status, AJAX.statusText, AJAX if AJAX.readyState is 4
} catch(e){console.log(“error”,e);};
AJAX = pndr.createXMLHttpRequest()
hit = ->
try {
AJAX.onreadystatechange = handler
BLOCK = false
ASYNC = true
AJAX.open verb, url, BLOCK
FireFox breaks on AJAX.withCredentials, but it is needed at bookmarking time
console.log(“AJAX.withCredentials:”,AJAX.withCredentials);
if typeof AJAX.withCredentials isnt "undefined"
can not happen before AJAX.open
try
AJAX.withCredentials = "true"
catch e
pndr.show_message "Please try a better supported browser: " + SUPPORTED_BROWSERS, 15
console.log "failure to fetch authenticated data because", e
if json_to_send
AJAX.setRequestHeader "Content-type", "application/json"
AJAX.send json_to_save
else
AJAX.send()
} catch(e){console.log(“error”,e);};
hit()
createXMLHttpRequest: ->
FIXME switch over to $.ajax it handles cross-browser issues
See http://en.wikipedia.org/wiki/XMLHttpRequest Provide the XMLHttpRequest class for IE 5.x-6.x:
if typeof XMLHttpRequest is "undefined"
xMLHttpRequest = ->
try
return new ActiveXObject("Msxml2.XMLHTTP.6.0")
try
return new ActiveXObject("Msxml2.XMLHTTP.3.0")
try
return new ActiveXObject("Msxml2.XMLHTTP")
try
return new ActiveXObject("Microsoft.XMLHTTP")
throw new Error("This browser does not support XMLHttpRequest.")
else
xMLHttpRequest = XMLHttpRequest
xhr = new xMLHttpRequest()
if (xhr.withCredentials){
xrh.withCredentials = "true";
}
xhr
criteria_for_saving: (args) ->
out = []
for i of ptw_vars.criteria_by_row_idx
out.push ptw_vars.criteria_by_row_idx[i].pack_crit_for_saving()
out
candidates_for_saving: (args) ->
out = []
for i of ptw_vars.candidates_by_row_idx
out.push ptw_vars.candidates_by_row_idx[i].pack_cand_for_saving()
out
candidate_data_for_saving: (args) ->
out = []
for i of ptw_vars.candidates_by_row_idx
out = out.concat(ptw_vars.candidates_by_row_idx[i].data_for_saving())
out
display_criterion_valuetype_selector: (evt) ->
a_row = evt.target.parentNode.parentNode
a_crit = pndr.get_criterion_by_idx(a_row.sectionRowIndex)
return a_crit.display_valuetype_selector()
set_select_to_value: (select_obj, to_value) ->
index = 0
while index < select_obj.children.length
if select_obj.children[index].value is to_value + ""
select_obj.selectedIndex = index
alert "set select to " + to_value
return true
index++
false
set_criterion_valuetype_handler: (evt) ->
criterion_id = evt.srcElement.id.split("__")[0]
criterion_obj = ptw_vars.criteria_by_their_id[criterion_id]
console.log(evt,criterion_id);
if (is_defined(criterion_obj.valuetype_id())) and (criterion_obj.num_of_candidates_with_non_defaulted_data() > 0) and criterion_obj.data_will_be_lost_if_valuetype_changes_to(evt)
unless confirm("Data might be lost, is that OK?")
pndr.set_select_to_value evt.srcElement.value, criterion_obj.valuetype_id()
criterion_obj.update_crit_visible()
return false
these 2 lines meant to turn of second pass thru this handler…
evt.target.onblur = null
evt.target.onchange = null
criterion_obj.valuetype_id evt.target.value
criterion_obj.discover_valuetype()
criterion_obj.update_crit_visible()
pndr.update_column_for_candidates criterion_obj
true
get_datum_by_input_element_id: (input_element_id) ->
splits = input_element_id.split("__")
crit_id = splits[0]
crit_obj = ptw_vars.criteria_by_their_id[crit_id]
cand_id = splits[1]
cand_obj = ptw_vars.candidates_by_their_id[cand_id]
cand_obj.datum_for_crit_id(crit_id)
set_datum_value: (evt) ->
a_datum = pndr.get_datum_by_input_element_id(evt.srcElement.id)
a_datum.set_value evt.target.value
update_column_for_candidates: (criterion_obj) ->
for i of ptw_vars.candidates_by_row_idx
cand_obj = ptw_vars.candidates_by_row_idx[i]
d_obj = cand_obj.ensure_datum_for_criterion(criterion_obj)
d_obj.update_datum_display()
populate_a_select: (args) ->
var_name = args["select_name"]
select_id = var_name
select_control = pndr.getElementsByClassName(var_name)[0] #.getElementById(select_id);
k = undefined
v = ptw_vars[var_name] # ie readable_by or writeable_by
out = ""
out += "<option value=\"\"></option>\n"
for k of choosable_agent_types
sel = ((if (k is v + "") then " selected" else ""))
console.log(k,choosable_agent_types[k],sel);
out += "<option" + sel + " value=\"" + k + "\">" + choosable_agent_types[k] + "</option>\n"
select_control.innerHTML = out
widget_id: (n) ->
if n
ptw_vars.widget_id = n
console.log(‘ptw_vars.table_id:’+ptw_vars.table_id);
ptw_vars.wgt_table = pndr.getElementsByClassName("ponderateTabularWidget")[0]
wgt = ptw_vars.wgt_table
captions = ptw_vars.wgt_table.getElementsByClassName("contentEditableInEditMode")
if (captions) captions[0].contentEditable = true; console.log “widget_id()”
ptw_vars.caption_elem = captions[0]
if ptw_vars.make_table_caption_draggable
how to make content editable AND draggable http://stackoverflow.com/a/10317527
pndr.make_caption_draggable_and_editable()
ptw_vars.candidate_rows = ptw_vars.wgt_table.tBodies[0]
ptw_vars.criterion_rows = ptw_vars.wgt_table.tHead
ptw_vars.windowshade = pndr.getElementsByClassName("windowShade")[0]
ptw_vars.windowShadeLabel = pndr.getElementsByClassName("windowShadeLabel")[0]
console.log “WS”, ptw_vars.windowshade
ptw_vars.windowshade.ondrag = pndr.ondrag_windowshade;
ptw_vars.windowshade.onclick = ptw_vars.ondrag_windowshade; $ = jquery;
Ponderate.jQuery = $ unless Ponderate.jQuery
pndr.initialize_windowshade()
ptw_vars.controls_id = n+’controls’; var pre = ptw_vars.table_id + ‘‘;
pndr.getElementsByClassName("addCriterionButton")[0].onclick = pndr.add_criterion_handler
pndr.getElementsByClassName("addCandidateButton")[0].onclick = pndr.add_candidate_handler
pndr.getElementsByClassName("saveButton")[0].onclick = pndr.save_all
if must_attachEvent
pndr.getElementsByClassName("editButton")[0].attachEvent "onclick", pndr.set_editing
pndr.getElementsByClassName("readable_by")[0].attachEvent "onchange", pndr.set_some_option
pndr.getElementsByClassName("writeable_by")[0].attachEvent "onchange", pndr.set_some_option
else
pndr.getElementsByClassName("editButton")[0].onclick = pndr.set_editing
pndr.getElementsByClassName("readable_by")[0].onchange = pndr.set_some_option
pndr.getElementsByClassName("writeable_by")[0].onchange = pndr.set_some_option
ptw_vars.wgt_controls = pndr.getElementsByClassName("ptwControls")[0]
pndr.set_visibility_of_controls();
ptw_vars.widget_id
initialize_windowshade: ->
shade_grain_px = 28
$(ptw_vars.windowshade).draggable
axis: "y"
grid: [shade_grain_px, shade_grain_px]
start: (event, ui) ->
console.clear()
set to zero if no value (or already zero!)
ptw_vars.num_crit_shaded = 0 unless ptw_vars.num_crit_shaded
we keep track of how many criteria have been shaded during this drag
ptw_vars.num_crit_shaded_this_drag = 0
and how much that number has changed since last ‘drag:’ was called
ptw_vars.num_crit_shaded_this_drag_last = 0
stop: (event, ui) ->
console.log “stop() num_crit_shaded:”, ptw_vars.num_crit_shaded
pndr.sort_candidates_by_criteria()
$(event.target).css "top", "0px"
ptw_vars.num_crit_shaded_this_drag = 0
drag: (event, ui) ->
console.log(“drag() num_crit_shaded:”,ptw_vars.num_crit_shaded); console.log(event,ui);
number_shaded = 0
Record the current state of num_crit_shaded_this_drag
ptw_vars.num_crit_shaded_this_drag_last = ptw_vars.num_crit_shaded_this_drag
Think about this as being about shading (rather than about showing). As a consequence we apply the multiplier of -1 (to set that polarity).
crit_shaded_this_drag = ui.position.top / shade_grain_px * -1
num_crit = pndr.get_num_criteria()
If dragging up overshoots the top stop at shading all
if crit_shaded_this_drag > num_crit
crit_shaded_this_drag = num_crit
ptw_vars.num_crit_shaded_this_drag = crit_shaded_this_drag
console.log “crit_shaded_this_drag”, crit_shaded_this_drag
keep the windowShade from drifting away from its row
ui.position.top = 0
any motion since last call to drag has been below threshold, so…
if ptw_vars.num_crit_shaded_this_drag_last is ptw_vars.num_crit_shaded_this_drag
return
So, if we get to here then there has been a change in the number of criteria the user wants to shade.
delta = ptw_vars.num_crit_shaded_this_drag - ptw_vars.num_crit_shaded_this_drag_last
ptw_vars.num_crit_shaded += delta
If drag overshoots, max out at the number of crits
if ptw_vars.num_crit_shaded > ptw_vars.criteria_by_row_idx.length
ptw_vars.num_crit_shaded = ptw_vars.criteria_by_row_idx.length - 1
If dragging down overshoots the bottom stop at zero to shade
if ptw_vars.num_crit_shaded <= 0
ptw_vars.num_crit_shaded = 0
pndr.reshade()
pndr.update_windowShadeLabel()
return
get_stylesheet_link: (SHEET_NAME) ->
SHEET_NAME_patt = new RegExp("SHEET_NAME", "g")
retval = pndr.replace_BASE_URL(ptw_vars.stylesheet_link_tmpl).replace(SHEET_NAME_patt, SHEET_NAME)
retval
get_ponderate_origin_url: ->
return ptw_vars.origin_url; console.log(“WINDOW.LOCATION=”,window.location);
Ponderate.canonical_origin_url
replace_BASE_URL: (s) ->
s.replace new RegExp("BASE_URL", "g"), pndr.get_ponderate_origin_url()
replace_PNDR_ID: (s) ->
This is VERY HACKY. It should work in the old Ponderate contexts and in Nooron’s new VisualizationController context where pndr_id is not set but table_id IS set. TODO clean this up!!!
if ptw_vars.pndr_id
retval = s.replace(new RegExp("PNDR_ID", "g"), ptw_vars.pndr_id)
else
retval = s.replace(new RegExp("ptw__PNDR_ID", "g"), ptw_vars.table_id)
retval
get_template_by_name: (template_name) ->
WIP: the hit is happening but the callback never happens
template_value = undefined
console.log "get_template_by_name(\"" + template_name + "\")"
$.ajax
type: "GET"
async: false
url: "/templates/" + template_name
dataType: "xml"
success: (data) ->
console.log "callback"
template_value = data
console.log "template_value =", template_value
retval = pndr.replace_BASE_URL(pndr.replace_PNDR_ID(template_value))
retval
get_widget_html: (args) ->
patt = new RegExp(ptw_defaults.table_id, "g")
retval2 = pndr.replace_BASE_URL(pndr.replace_PNDR_ID(widget_html))
retval2
frame_id: (fid) ->
ptw_vars.frame_id = fid if is_defined(fid)
ptw_vars.frame_id
get_or_make_frame: ->
if not ptw_vars.wgt_frame?
ptw_vars.wgt_frame = document.getElementById(pndr.frame_id())
unless ptw_vars.wgt_frame
document.write "<div id=\"" + pndr.frame_id() + "\"></div>"
ptw_vars.wgt_frame = document.getElementById(pndr.frame_id())
document_write_widget: (args) ->
document.write(pndr.get_stylesheet_link(‘writingOff’)); document.write(pndr.get_stylesheet_link(‘editingOff’)); document.write(pndr.get_stylesheet_link(‘tabular_widget’)); console.log “ptw_vars::”, ptw_vars, “pndr::”, pndr
pndr.get_or_make_frame()
ptw_vars.wgt_frame.innerHTML = pndr.get_widget_html()
document.write(pndr.get_widget_html());
ptw_vars.widget_id = ptw_vars.table_id
pndr.widget_id ptw_vars.table_id
is the following really needed here?!? ptw_vars.candidate_rows = ptw_vars.wgt_table.tBodies[0];
pndr.install_stylesheet();
pndr.set_visibility_of_controls()
pndr.hide_or_show_footer()
hide_or_show_footer: ->
if ptw_vars.hide_footer
sel = 'div#pndr_'+ptw_vars.pndr_id+', tfoot'
$(sel).hide()
show_message: (msg, timeout) ->
FIXME show message somewhere ptw_vars.wgt_frame.getElementsByClassName(‘messageBox’)[0].innerHTML = msg; self.getElementsByClassName(‘messageBox’)[0].innerHTML = msg;
console.log "SHOW_MESSAGE", msg if msg
pndr.getElementsByClassName(‘messageBox’)[0].innerHTML = ‘’;
get_url_to_ponder_json: (pndr_id) ->
ptw_vars.origin_url + "/pndr8/" + pndr_id + ".json"
is_bookmarking_mode: (b) ->
ptw_vars.is_bookmarking_mode = b if is_boolean(b)
ptw_vars.is_bookmarking_mode
set_created_by: (literal) ->
console.log "set_created_by",literal
$('div#pndr_'+ptw_vars.pndr_id+' span.createdBy').html(literal)
set_authenticated_user: (account_obj) ->
ptw_vars.authenticated_user = account_obj
ptw_vars.authenticated_username = account_obj.account_key
Lets also keep a list of the various identifiers for the pserson to make it possible to detect them at sort time.
ptw_vars.account_names = an = []
if account_obj
au = account_obj
if au.displayName?
an.push(au.displayName)
if au.account_key?
an.push(au.account_key) unless au.account_key in an
Because who is logged on can affect the sorting of the username column of the /pndr/00000000000000 page we need to trigger a re-sort when ponderae_authenticated_user gets updated
pndr.sort_candidates_by_criteria()
get_account_names: () ->
ptw_vars.account_names || []
get_authenticated_username: ->
ptw_vars.authenticated_username
reject_old_browsers: ->
if navigator.userAgent.match(/MSIE\s(?!9.0)/)
This is a crude attempt to tell if we have a modern browser It should fail on IE < 9 and pass on Chrome, Safari and IE9
document.body.innerHTML += "<h2>Sorry, Ponderate needs a more modern browser. " + SUPPORTED_BROWSERS + " work best and IE9 can work for display.</h2>"
true
else
false
subscribe_widget_to_cmd: (args, cmd) ->
add_candidates_from_frames = (details_list) ->
i = 0
while i < details_list.length
frame_details = details_list[i]
cand_spec =
id: frame_details.handle
label: frame_details.pretty_name
pndr.add_candidate cand_spec
i++
args.noor.subscribe(cmd,add_candidates_from_frames);
add_candidates_from_frames [
handle: "bob"
pretty_name: "Robert"
]
make_widget_here: (args) ->
args = args or {}
console.log “make_widget_here:”, args.pndr_id, args
return if pndr.reject_old_browser
copy_props_from_to_([
"add_candidate_label", "add_candidate_url", "base_url",
"show_edit_button", "pndr_id", "origin_url",
"add_current_page_as_candidate", "being_edited",
"show_edit_button", "readable_by", "writeable_by",
"frame_id", "authenticated_username", "is_bookmarking_mode"],
args, ptw_vars)
if args.noor
pndr.show_message "loading data"
args.src = "URL_FOR_THIS_PNDR"
pndr.fill_widget_with_json_from_url args
pndr.document_write_widget args
pndr.subscribe_widget_to_cmd args,
op: "get_kbs"
pndr.show_message()
pndr.populate_a_select({select_name: ‘writeable_by’}); pndr.populate_a_select({select_name: ‘readable_by’});
else if args.pndr_id
console.log “about to load data for pndr_id:”, args.pndr_id ptw_vars.pndr_id = args.pndr_id;
pndr.show_message "loading data"
args.src = pndr.get_url_to_ponder_json(args.pndr_id)
pndr.fill_widget_with_json_from_url args
pndr.show_message()
else if args.simple_list
pndr.pndr8_title = args.title
pndr.document_write_widget(args)
else
new ponder
ptw_vars.being_edited = true
pndr.show_message "loading data"
args.src = pndr.get_url_to_ponder_json(args.pndr_id)
pndr.fill_widget_with_json_from_url(args);
pndr.show_message()
pndr.document_write_widget args
pndr.populate_a_select select_name: "writeable_by"
pndr.populate_a_select select_name: "readable_by"
console.log(“args for new ponder”,args);
pndr.pndr8_title args.title if args.title
pndr.add_current_page_as_candidate() if ptw_vars.add_current_page_as_candidate
console.log(“being_edited”,pndr.being_edited()); console.log(“show_edit_button”,ptw_vars.show_edit_button); console.log(“PTW”,ptw_vars); alert(“make_widget_here(ptw_vars=”+JSON.stringify(ptw_vars)+”)”);
pndr
add_current_page_as_candidate: (args) ->
pndr.add_candidate
row_idx: 0
vet_label: true
vet_url: true
url: document.location.href
label: document.title
sort_candidates_if_unsorted: (args) ->
console.log(‘sort_candidates_if_unsorted’);
pndr.sort_candidates_by_criteria() if pndr.candidates_unsorted()
sort_candidates_by_criteria: (args) ->
window.current_user_shown = false
OK, this is relatively tricky. The goal is to sort the list of candidates by a table of data in columns given by the criteria. The objective is to perform a sort equivalent to an SQL grouped sort, so if the first column to sort on has equal values in it then the second column drives the sort and if they are equal then the third and so on.
pndr.recursive_sort_rows_by_crit_list
This routine is further complicated by the fact that we want to remain agnostic about where the ordered list of criteria (columns to sort by) are coming from. Initally the leftmost column is considered, the the second from the left, and so on, but we might want a different user experience to drive the specification of the ordering. Maybe the columns to sort on will be flagged with numbers inidcating their priority in the sequence, etc. But the abstraction boundry about that is HERE. So the order of the ‘criteria:’ is what will drive the search.
criteria: ptw_vars.criteria_by_row_idx
The items to be moved are actually the TR elements in the TRs argument.
trs: ptw_vars.candidate_rows
Furthermore the data is in one structure (the ‘candidates:’) but the things to be moved are actually the TRs in the ‘TRs’ variable. In particular, the data are in the candidates, accessible using get_datum_by_crit_id().
candidates: ptw_vars.candidates_by_row_idx
recursive_sort_rows_by_crit_list: (args) ->
So, the sort has been specified ouside of here. The question now is how to accomplish it. Here is what we’ll do: everything we can to make it fast. We will build a grand_comparitor function which is composed of the comparitor functions provided by each of the criteria, because (of course) the criteria have associated ‘valuetypes’ which can be very strange indeed, having nonalphanumeric sorting properties like ‘severe’ > ‘moderate’ > ‘trivial’ or ‘gale’ > ‘breeze’. The criterion-provided comparitors will also embody the native ‘ASCending’ vs ‘DESCending’ default associated with that valuetype. The windspeed criterion would default to ‘ASC’ while letter_grade would default to ‘DESC’ and dollars would default to ‘ASC’. The comparitor will sort a two dimensional array of values from the candidate rows and criterion columns. This two dimensional array will be built lazily, that is: iff the first column is detected by the comparitor framework to be insufficent to provide a ‘complete’ order (ie it detects equality at runtime between a pair of elements) then the on the needed portions of the second column will be obtained, and so on until an inequality is discovered between the two candidates or we run out of criteria. var gc =
candidate_ids_in_new_order = pndr.get_sorted_candidate_ids(args)
pndr.reorder_table_rows_according_to_candidate_order candidate_ids_in_new_order
reorder_table_rows_according_to_candidate_order: (new_order) ->
first move every one of the TRs into the tBody in the new order
i = undefined
cand = undefined
i = 0
while i < ptw_vars.candidates_by_row_idx.length
cand = ptw_vars.candidates_by_row_idx[i]
continue unless cand
console.log(i,”is now “,cand.label());
tr = cand.tr()
see ref#8
if i + 1 >= ptw_vars.candidates_by_row_idx.length
ptw_vars.candidate_rows.appendChild tr
else
ptw_vars.candidate_rows.insertBefore tr, ptw_vars.candidate_rows.children[i + 1]
cand.idx i
i++
ensure that candidates_by_row_idx is properly indexed
for i of ptw_vars.candidates_by_their_id
cand = ptw_vars.candidates_by_their_id[i]
console.log(“registering “+cand.label()+” at “+cand.idx());
ptw_vars.candidates_by_row_idx[cand.idx()] = cand
get_sorted_candidate_ids: (args) ->
In args we look for both the list args.criteria and optionally, the object args.directions, which (if it is present) will be keyed by the crit.id() and contain the values ‘ASC’|’DESC’|undefined, undefined meaning that criterion should not participate in the ordering.
crit_comparitors = []
num_crit_shown = pndr.get_num_crit_unshaded()
console.log(‘shown:’,num_crit_shown);
idx = 0
while idx < args.criteria.length
crit_obj = args.criteria[idx]
if idx < num_crit_shown
crit_comparitors.push
cmp: crit_obj.get_cmp(args)
id: crit_obj.id()
idx++
grand_comparitor = (cand_a, cand_b) ->
cand_a and cand_b are candidate objects with method get_datum_by_crit_id
retval = 0
indent = ""
console.log(“crit_comparitors:”,crit_comparitors);
cci = 0
while cci < crit_comparitors.length
crit_id = crit_comparitors[cci].id
crit = ptw_vars.criteria_by_their_id[crit_id]
cmp = crit_comparitors[cci].cmp
datum_a = cand_a.get_datum_by_crit_id(crit_id)
datum_b = cand_b.get_datum_by_crit_id(crit_id)
console.log(‘datum_a =’,datum_a);
val_a = (if is_defined(datum_a) then datum_a.datum_coerce_to_valuetype() else `undefined`)
val_b = (if is_defined(datum_b) then datum_b.datum_coerce_to_valuetype() else `undefined`)
using = undefined
if is_defined(val_a) and is_defined(val_b)
using = "cmp"
retval = cmp(val_a, val_b)
else if is_defined(val_a) and is_undefined(val_b)
using = "d&u"
retval = -1
else if is_undefined(val_a) and is_defined(val_b)
using = "u&d"
retval = 1
else if is_undefined(val_a) and is_undefined(val_b)
using = "u&u"
retval = 0
retval = retval * crit.default_order()
summary = indent + "comparing " + using + " " + val_a + " and " + val_b + " ===> " + retval
console.log summary if window.DEBUG_COMPARITOR
console.log(crit.label(),cand_a.label(),retval,cand_b.label());
return retval if retval isnt 0
indent += " "
cci++
retval = ascending_cmp(cand_a.label(), cand_b.label()) if retval is 0
retval
args.candidates.sort grand_comparitor
fill_widget_from_ponderspec: (args) ->
i = undefined
ponderspec = args.ponderspec
if (window.location.href.search(‘EDIT’) > -1){ ptw_vars.show_edit_button = true;
if ptw_vars.show_edit_button
pndr.set_visibility_of_controls()
if ptw_vars.add_candidate_label
adcand = pndr.getElementsByClassName("addCandidateButton")[0]
adcand.value = ptw_vars.add_candidate_label
These should be settable using the initial constructor Hmm. Do we really need the constructor and ‘make_widget_here’? Possibly. Let’s clean up as much as possible right now.
copy_props_from_to_ [
"readable_by", "writeable_by", "created_by", "creator_account",
"modification_time", "creation_time", "authenticated_username"],
ponderspec, ptw_vars
pndr.populate_a_select select_name: "writeable_by"
pndr.populate_a_select select_name: "readable_by"
if not ptw_vars.creator_account?
console.log "creator_account is undefined"
pndr.set_created_by(ptw_vars.creator_account?.displayName ||
ptw_vars.creator_account?.account_key ||
ptw_vars.created_by || 'hmm...')
if ponderspec.name
pndr.pndr8_title ponderspec.name
else
pndr.pndr8_title ptw_vars.pndr8_title
pndr.ponderation_id ponderspec["_id"] if ponderspec["_id"]
if ponderspec.candidates
i = 0
while i < ponderspec.candidates.length
pndr.add_candidate ponderspec.candidates[i]
i++
if ponderspec.criteria
i = 0
while i < ponderspec.criteria.length
pndr.add_criterion ponderspec.criteria[i]
i++
if ponderspec.data
i = 0
while i < ponderspec.data.length
datum_spec = ponderspec.data[i]
pndr.add_datum datum_spec if has_value(datum_spec)
i++
pndr.sort_candidates_if_unsorted()
pndr.make_candidates_draggable_if_needed()
pndr
make_candidates_draggable_if_needed: ->
if ptw_vars.candidate__drop_handler
$(".candidateCell").attr("style","background-color:yellow")
$(".candidateCell").draggable
simple_helper: "clone"
helper: (e, ui) ->
return $(this).clone().appendTo('body').css('zIndex', 5).show()
handle: ".candidateDragHandle"
stop: ptw_vars.candidate__drop_handler
start: ptw_vars.candidate__drag_start_handler
##
pndr
alert(window.location.href+” “+window.location.href.search(‘show_edit’));
add_arrow_cell_to: (args) ->
arrow_cell = args.target.insertCell(0)
arrow_cell.setAttribute "class", "arrow_box"
arrow_cell.setAttribute "rowspan", 1
hide this arrow if it is on the first row
$(arrow_cell).hide() if args.target.rowIndex is 0
arrow_cell.innerHTML = ptw_vars.basic_arrow; // replaced by bg via css
being_edited: (b) ->
if typeof (b) is typeof (true)
ptw_vars.being_edited = b
ptw_vars.being_edited
is_spreadsheet_mode: ->
return ptw_vars.interaction_mode is 'spreadsheet'
is_document_mode: ->
return ptw_vars.interaction_mode is 'document'
make_cell_value_onchange_handler: (cell) ->
return (evt) ->
ptw_vars.cell_value_onchange_handler(evt, cell)
get_num_crit_unshaded: (args) ->
pndr.get_num_criteria() - ptw_vars.num_crit_shaded
get_num_criteria: (args) ->
ptw_vars.wgt_table.tHead.children.length - 1
get_num_columns: (args) ->
ptw_vars.wgt_table.tHead.children.length
add_column_to_candidates: (args) ->
console.log(‘adding column ‘,args.crit_obj.label(), ‘ to candidates’);
a_cand_row = undefined
console.log(“candidate_rows:”,ptw_vars.candidate_rows); var candidate_rows = ptw_vars.candidate_rows; console.log(‘num candidates:’,ptw_vars.candidate_rows.children.length); console.log(ptw_vars.candidates_by_row_idx); for (var idx = 0; idx <= ptw_vars.candidate_rows.childElementCount; idx++){
idx = 0
while idx < ptw_vars.candidates_by_row_idx.length
a_cand_row = ptw_vars.candidate_rows.children[idx]
continue unless a_cand_row # TODO(shawn) were you being paid by the mystery?
a_cand_obj = ptw_vars.candidates_by_row_idx[idx]
continue unless a_cand_obj # TODO(shawn) were you being paid by the misery?
a_cand_obj.add_column args
idx++
get_valuetype_by_id: (valuetype_id) ->
valuetype_factory.get valuetype_id
push_down_criteria: (args) ->
a_crit_row = undefined
TODO de-clever the following horror (maybe see what the javascript is doing!)
pndr.add_arrow_cell_to target: ptw_vars.wgt_controls if ptw_vars.wgt_controls.children.length < 2
thead = ptw_vars.wgt_table.tHead
idx = thead.children.length - 1
while idx > -1
a_crit_row = thead.children[idx]
a_criterion = ptw_vars.criteria_by_row_idx[idx]
TODO vewwy vewwy kawfuwwy unfuck this construct
continue if args.except.row_idx is idx if args.except isnt `undefined`
if (idx == 0) continue;
if a_criterion
a_criterion.push_down()
idx--
wait: (msecs) ->
start = new Date().getTime()
cur = start
cur = new Date().getTime() while cur - start < msecs
ponderation_id: (s) ->
ptw_vars._id = s if typeof (s) is typeof ("")
ptw_vars._id
has_unsaved_changes: (b) ->
ptw_vars.has_unsaved_changes = b if typeof (b) is "boolean"
ptw_vars.has_unsaved_changes
write_to_storage: (obj) ->
This will write to the server or local storage as needed. return true when that works. If true, there is no need for dirtiness, the save button, etc. If false, the save button is needed.
false
ondrag_windowshade: (args) ->
console.log "ondrag", args
console.log "arguments", arguments_
candidates_unsorted: (b) ->
ptw_vars.candidates_unsorted = b if is_boolean(b)
ptw_vars.candidates_unsorted or false
xsd_to_valuetype: (xsd_type) ->
return xsd_type_to_valuetype(xsd_type)
pndr = that
return pndr
if document?
document.ontouchmove = (e) ->
e.preventDefault()
(exports ? this).localize_iso8601 = localize_iso8601
(exports ? this).validate_iso8601 = validate_iso8601
(exports ? this).tabular_widget = tabular_widget
console.log(“loading tabular_widget.js”); Ponderate.op_queue__drain();
if Ponderate.set_of_params
console.log "Ponderate.set_of_params() =", Ponderate.set_of_params
window.ptw = Ponderate.tabular_widget(); Ponderate.register(ptw.make_width_here(Ponderate.set_of_params[0]));
Ponderate.embed_desired_widget()