To allow scrolling in Safari mobile, we set the content of text_view_comments frame in a jQuery UI layout.
So the automated scrolling operations in c_sync.js must be adjustable to the right part to scroll.
Also, if a comment have to be shown outside of the current viewport, we scroll the correct part to that viewport
and then set the comment top Y offset to juste what it needs to avoid the "Add comment" button after scrolling
operation.
If not in Safari mobile, we add an offset here to avoid comment to display under the "Add comment" button.
import difflib, string
from django.utils.translation import ugettext as _
def isatag(x): return x.startswith("<") and x.endswith(">")
def text_diff(a, b):
res = []
a, b = createlist(a), createlist(b)
s = difflib.SequenceMatcher(isatag, a, b)
for e in s.get_opcodes():
if e[0] == "replace":
res.append('<del class="diff modified">'+''.join(a[e[1]:e[2]]) + '</del><ins class="diff modified">'+''.join(b[e[3]:e[4]])+"</ins>")
elif e[0] == "delete":
res.append('<del class="diff">'+ ''.join(a[e[1]:e[2]]) + "</del>")
elif e[0] == "insert":
res.append('<ins class="diff">'+''.join(b[e[3]:e[4]]) + "</ins>")
elif e[0] == "equal":
res.append(''.join(b[e[3]:e[4]]))
else:
raise "error parsing %s" %(e[0])
return ''.join(res)
COLORS = [
'#FF0000',
'#EE0000',
'#DD0000',
'#CC0000',
'#BB0000',
'#AA0000',
'#990000',
'#880000',
'#770000',
]
from colorsys import hls_to_rgb, hsv_to_rgb
def generatePastelColors(n):
s = .4
v = .99
return ['#'+''.join((hex(int(r*255))[2:],hex(int(g*255))[2:],hex(int(b*255))[2:])) for r,g,b in [hsv_to_rgb(h/200.,s,v) for h in range(1,100,100/n)]]
DEFAULT_COLOR = '#D9D9D9'
def get_colors(authors, last_white = False):
"""
returns a dict for authors's colors (with last one white if 'last_white')
"""
authors = set(authors)
#new_colors = list(tuple(COLORS))
new_colors = generatePastelColors(len(set(authors)))
res = []
if None in authors or '' in authors:
res = [(_(u'unknown'),DEFAULT_COLOR) ]
res.extend([(author,new_colors.pop()) for author in authors if author])
#if authors[-1]:
# res[authors[-1]] = '#FFFFFF'
return res
def text_history(versions, authors):
res = versions[0]
colors = get_colors(authors)
for ind in range(len(versions)-1):
author = authors[ind]
color = colors.get(author,DEFAULT_COLOR)
v_2 = versions[ind + 1]
res = text_diff_add(v_2, res, color)
return res,colors.items()
from cm.utils.html import surrond_text_node
def text_diff_add(a,b, color):
res = []
a, b = createlist(a), createlist(b)
s = difflib.SequenceMatcher(isatag, a, b)
for e in s.get_opcodes():
if e[0] == "replace":
html_chunk = ''.join(b[e[3]:e[4]])
new_html_chunk = surrond_text_node(html_chunk,'<span style="background: %s;">' %color,'</span>')
res.append(new_html_chunk)
#res.append('<font style="background: %s;" class="diff modified">' %color+''.join(b[e[3]:e[4]])+"</font>")
elif e[0] == "delete":
pass
elif e[0] == "insert":
html_chunk = ''.join(b[e[3]:e[4]])
new_html_chunk = surrond_text_node(html_chunk,'<span style="background: %s;">' %color,'</span>')
res.append(new_html_chunk)
#res.append('<font style="background: %s;" class="diff">' %color+''.join(b[e[3]:e[4]]) + "</font>")
elif e[0] == "equal":
res.append(''.join(b[e[3]:e[4]]))
else:
raise "error parsing %s" %(e[0])
return ''.join(res)
def createlist(x, b=0):
mode = 'char'
cur = ''
out = []
for c in x:
if mode == 'tag':
if c == '>':
if b: cur += ']'
else: cur += c
out.append(cur); cur = ''; mode = 'char'
else: cur += c
elif mode == 'char':
if c == '<':
out.append(cur)
if b: cur = '['
else: cur = c
mode = 'tag'
elif c in string.whitespace: out.append(cur+c); cur = ''
else: cur += c
out.append(cur)
return filter(lambda x: x is not '', out)
#
from cm.ext.diff_match_patch import diff_match_patch
class diff_match_patch2(diff_match_patch):
def diff_prettyHtml_one_way(self, diffs, way=False, mode='red'):
"""Convert a diff array into a pretty HTML report.
Args:
diffs: Array of diff tuples.
way: [None, 1, 2]
mode: ['ins_del', 'red']
Returns:
HTML representation.
"""
html = []
i = 0
for (op, data) in diffs:
text = data #(data.replace("&", "&").replace("<", "<")
#.replace(">", ">").replace("\n", "¶<BR>"))
if op == self.DIFF_INSERT and (not way or way==1):
if mode=='red':
html.append('<span class="diffchange-ins">%s</span>' % (text))
else:
html.append('<ins>%s</ins>' % (text))
elif op == self.DIFF_DELETE and (not way or way==2):
if mode=='red':
html.append('<span class="diffchange-del">%s</span>'% (text))
else:
html.append('<del>%s</del>'% (text))
elif op == self.DIFF_EQUAL:
html.append("<SPAN>%s</SPAN>" % (text))
if op != self.DIFF_DELETE:
i += len(data)
return "".join(html)