[livejournal] r18407: LJSUP-7848: spam button popup and new "d...
Committer: szhirkov
LJSUP-7848: spam button popup and new "delete comment" popupU trunk/htdocs/js/commentmanage.js
Modified: trunk/htdocs/js/commentmanage.js
===================================================================
--- trunk/htdocs/js/commentmanage.js 2011-02-25 03:24:03 UTC (rev 18406)
+++ trunk/htdocs/js/commentmanage.js 2011-02-25 05:12:46 UTC (rev 18407)
@@ -60,6 +60,16 @@
}
}
+function getLocalizedStr( key, username ) {
+ var str = "";
+ if( key in Site.ml_text ) {
+ str = Site.ml_text[ key ];
+ str = str.replace( '%username%', username );
+ }
+
+ return str;
+}
+
// hsv to rgb
// h, s, v = [0, 1), [0, 1], [0, 1]
// r, g, b = [0, 255], [0, 255], [0, 255]
@@ -90,15 +100,16 @@
return [v,p,q];
}
-var curPopup = null;
-var curPopup_id = 0;
+window.curPopup = null;
+window.curPopup_id = 0;
function killPopup () {
- if (!curPopup)
- return true;
+ if (!window.curPopup) {
+ return true;
+ }
- var popup = curPopup;
- curPopup = null;
+ var popup = window.curPopup;
+ window.curPopup = null;
var opp = 1.0;
@@ -114,10 +125,167 @@
}
};
fade();
+
+ jQuery(document).unbind('.commentManagePopup');
return true;
}
+/**
+ * Create popup element, insert content and show it with animation
+ *
+ * @param {String} contentHtml
+ * @param {DOM} targetControl
+ * @param {Object} e
+ * @param {String} id
+ */
+function createPopup(contentHtml, targetControl, e, id) {
+ targetControl = jQuery(targetControl).find('img');
+
+ var popupElem = jQuery('<div class="ljcmtmanage b-popup"><div class="b-popup-outer"><div class="b-popup-inner"><div class="ljcmtmanage-content"></div><i class="i-popup-arr i-popup-arrtl"></i><i class="i-popup-close"></i></div></div></div>'),
+
+ popupCloseControlSelector = '.i-popup-close',
+ popupArrowSelector = '.i-popup-arr',
+ popupContentSelector = '.ljcmtmanage-content',
+
+ popupContent = popupElem.find(popupContentSelector),
+ popupArrow = popupElem.find(popupArrowSelector),
+
+ targetOffset = targetControl.offset();
+
+ // popup already exist
+ if (window.curPopup) {
+ if (window.curPopup_id == id) {
+ e.stopPropagation();
+ return false;
+ }
+
+ killPopup();
+ }
+
+ popupContent.html(contentHtml);
+
+ popupElem
+ .delegate(popupCloseControlSelector, 'click', killPopup)
+ .click(function (e) { e.stopPropagation(); })
+
+ .appendTo('body')
+
+ .css({
+ visibility: 'visible',
+ opacity: 0
+ });
+
+
+ placeElemNear(popupElem, targetControl);
+ showSmooth(popupElem);
+
+ window.curPopup = popupElem[0];
+ window.curPopup_id = id;
+
+ jQuery(document).bind('click.commentManagePopup keydown.commentManagePopup', function (e) {
+ if ((e.type == 'keydown' && e.keyCode == 27) || e.type != 'keydown') {
+ killPopup();
+ }
+ });
+
+ function placeElemNear(elem, target) {
+ /**
+ * Popup types
+ *
+ * * -^--- *
+ * tl | |
+ * * ----- *
+ *
+ * * ---^- *
+ * tr | |
+ * * ----- *
+ *
+ * * ----- *
+ * bl | |
+ * * -V--- *
+ *
+ * * ----- *
+ * br | |
+ * * ---V- *
+ */
+
+ var classNamePrefix = 'i-popup-arr',
+
+ viewport = jQuery(window),
+ viewportWidth = viewport.width(),
+ viewportHeight = viewport.height(),
+
+ elemWidth = elem.width(),
+ elemHeight = elem.height(),
+
+ positionType = {
+ x: 'l', // left
+ y: 't' // top
+ },
+ positionTypes = {
+ 'tl': function () {
+ return {
+ x: targetOffset.left - popupArrow.position().left - (popupArrow.width() / 2) + (targetControl.width() / 2),
+ y: targetOffset.top + popupArrow.height() - popupArrow.position().top + (targetControl.height() / 2)
+ };
+ },
+ 'tr': function () {
+ return {
+ x: targetOffset.left - popupArrow.position().left - (popupArrow.width() / 2) + (targetControl.width() / 2),
+ y: targetOffset.top + popupArrow.height() - popupArrow.position().top + (targetControl.height() / 2)
+ };
+ },
+ 'bl': function () {
+ return {
+ x: targetOffset.left - popupArrow.position().left - (popupArrow.width() / 2) + (targetControl.width() / 2),
+ y: targetOffset.top - popupArrow.height() - elemHeight
+ };
+ },
+ 'br': function () {
+ return {
+ x: targetOffset.left - popupArrow.position().left - (popupArrow.width() / 2) + (targetControl.width() / 2),
+ y: targetOffset.top - popupArrow.height() - elemHeight
+ };
+ }
+ },
+ position,
+
+ checkAngle = {
+ x: positionTypes.tl().x + elemWidth,
+ y: positionTypes.tl().y + elemHeight
+ };
+
+ if (checkAngle.x > viewportWidth) {
+ positionType.x = 'r'; // right
+ }
+
+ if (checkAngle.y > viewportHeight + viewport.scrollTop()) {
+ positionType.y = 'b'; // bottom
+ }
+
+ positionType = positionType.y + positionType.x;
+ popupArrow.removeClass('i-popup-arrtl').addClass(classNamePrefix + positionType);
+ position = positionTypes[positionType]();
+
+ elem.css({
+ 'left': Math.floor(position.x) + 'px',
+ 'top': Math.floor(position.y) + 'px'
+ });
+ }
+
+ return popupElem;
+}
+
+function showSmooth(elem) {
+ var finalTop = parseInt(elem.css('top'), 10);
+ elem.css('top', finalTop - 20);
+ elem.animate({
+ opacity: 1,
+ top: finalTop
+ }, 'fast');
+}
+
function deleteComment (ditemid, isS1) {
killPopup();
@@ -214,19 +382,11 @@
}
}
-function docClicked () {
- killPopup();
-
- // we didn't handle anything, who are we kidding
-}
-
-function createDeleteFunction (ae, dItemid, isS1) {
+function createDeleteFunction(ae, dItemid, isS1) {
return function (e) {
e = jQuery.event.fix(e || window.event);
- var finalHeight = 115;
-
- if (e.shiftKey || (curPopup && curPopup_id != dItemid)) {
+ if (e.shiftKey || (window.curPopup && window.curPopup_id != dItemid)) {
killPopup();
}
@@ -236,7 +396,7 @@
doIT = 1;
deleteComment(dItemid, isS1);
} else {
- if (! LJ_cmtinfo)
+ if (!LJ_cmtinfo)
return true;
var com = LJ_cmtinfo[dItemid];
@@ -245,90 +405,30 @@
return true;
var canAdmin = LJ_cmtinfo["canAdmin"];
- var pos_offset = jQuery(ae).position(),
- offset = jQuery(ae).offset(),
- pos_x = e.pageX + pos_offset.left - offset.left,
- top = e.pageY + pos_offset.top - offset.top + 5,
- left = Math.max(pos_x + 5 - 250, 5),
- $window = jQuery(window);
-
- //calc with viewport
- if ($window.scrollLeft() > left + offset.left - pos_offset.left) {
- left = $window.scrollLeft() + pos_offset.left - offset.left;
- }
-
- if (curPopup && curPopup_id == dItemid) {
- //calc with viewport
- top = Math.min(top, $window.height() + $window.scrollTop() - jQuery(curPopup).outerHeight() + pos_offset.top - offset.top);
- curPopup.style.left = left + 'px';
- curPopup.style.top = top + 'px';
-
- return Event.stop(e);
- }
-
- var de = jQuery('<div class="ljcmtmanage" style="text-align:left;position:absolute;visibility:hidden;width:250px;left:0;top:0;z-index:3"></div>')
- .click(function(e){
- e.stopPropagation()
- });
-
- var inHTML = "<form style='display: inline' id='ljdelopts" + dItemid + "'><span style='font-face: Arial; font-size: 8pt'><b>Delete comment?</b><br />";
+ var inHTML = [ "<form id='ljdelopts" + dItemid + "'><div class='b-popup-group'><div class='b-popup-row b-popup-row-head'><strong>" + getLocalizedStr( 'comment.delete.q', com.u ) + "</strong></div>" ];
var lbl;
if (com.username != "" && com.username != remoteUser && canAdmin) {
lbl = "ljpopdel" + dItemid + "ban";
- inHTML += "<input type='checkbox' name='ban' id='" + lbl + "'> <label for='" + lbl + "'>Ban <b>" + com.u + "</b> from commenting</label><br />";
- } else {
- finalHeight -= 15;
+ inHTML.push("<div class='b-popup-row'><input type='checkbox' name='ban' id='" + lbl + "'> <label for='" + lbl + "'>" + getLocalizedStr( 'comment.ban.user', com.u ) + "</label></div>");
}
if (remoteUser != com.username) {
lbl = "ljpopdel" + dItemid + "spam";
- inHTML += "<input type='checkbox' name='spam' id='" + lbl + "'> <label for='" + lbl + "'>Mark this comment as spam</label><br />";
- } else {
- finalHeight -= 15;
+ inHTML.push("<div class='b-popup-row'><input type='checkbox' name='spam' id='" + lbl + "'> <label for='" + lbl + "'>" + getLocalizedStr( 'comment.mark.spam', com.u ) + "</label></div>");
}
if (com.rc && com.rc.length && canAdmin) {
lbl = "ljpopdel" + dItemid + "thread";
- inHTML += "<input type='checkbox' name='delthread' id='" + lbl + "'> <label for='" + lbl + "'>Delete thread (all subcomments)</label><br />";
- } else {
- finalHeight -= 15;
+ inHTML.push("<div class='b-popup-row'><input type='checkbox' name='delthread' id='" + lbl + "'> <label for='" + lbl + "'>" + getLocalizedStr( 'comment.delete.all.sub', com.u ) + "</label></div>");
}
if (canAdmin&&com.username) {
lbl = "ljpopdel" + dItemid + "author";
- inHTML += "<input type='checkbox' name='delauthor' id='" + lbl + "'> <label for='" + lbl + "'>Delete all <b>" + (com.username == remoteUser ? 'my' : com.u) + "</b> comments in this post</label><br />";
- } else {
- finalHeight -= 15;
+ inHTML.push("<div class='b-popup-row'><input type='checkbox' name='delauthor' id='" + lbl + "'> <label for='" + lbl + "'>" + getLocalizedStr( 'comment.delete.all', "<b>" + ( (com.username == remoteUser ? 'my' : com.u) ) + "</b>" ) + "</label></div>");
}
- inHTML += "<input type='button' value='Delete' onclick='deleteComment(" + dItemid + ", " + isS1.toString() + ");' /> <input type='button' value='Cancel' onclick='killPopup()' /></span><br /><span style='font-face: Arial; font-size: 8pt'><i>shift-click to delete without options</i></span></form>";
+ inHTML.push("<div class='b-popup-row'><input type='button' value='" + getLocalizedStr( 'comment.delete', com.u ) + "' onclick='deleteComment(" + dItemid + ", " + isS1.toString() + ");' /></div></div><div class='b-bubble b-bubble-alert b-bubble-noarrow'><i class='i-bubble-arrow-border'></i><i class='i-bubble-arrow'></i>" + getLocalizedStr( 'comment.delete.no.options', com.u ) + "</div></form>");
- de.html(inHTML).insertAfter(ae);
-
- //calc with viewport
- top = Math.min(top, $window.height() + $window.scrollTop() - de.outerHeight() + pos_offset.top - offset.top);
-
- de.css({
- left: left,
- top: top,
- height: 10,
- visibility: 'visible',
- overflow: 'hidden'
- });
-
- curPopup = de[0];
- curPopup_id = dItemid;
-
- var height = 10;
- var grow = function () {
- height += 7;
- if (height > finalHeight) {
- de.height('auto');
- } else {
- de.height(height);
- window.setTimeout(grow, 20);
- }
- }
- grow();
+ createPopup(inHTML.join(' '), ae, e, 'deletePopup' + dItemid);
}
Event.stop(e);
}
@@ -395,146 +495,197 @@
}
var tsInProg = {} // dict of { ditemid => 1 }
-function createModerationFunction(ae, dItemid, isS1)
-{
- return function(e)
- {
- var e = jQuery.event.fix(e || window.event);
+function createModerationFunction(control, dItemid, isS1, action) {
+ var action = action || 'screen', // "screen" action by default
+ comUser = LJ_cmtinfo[dItemid].u;
+
+ return function (e) {
+ var e = jQuery.event.fix(e || window.event),
pos = { x: e.pageX, y: e.pageY },
- postUrl = ae.href.replace(/.+talkscreen\.bml/, LiveJournal.getAjaxUrl('talkscreen')),
+ modeParam = LiveJournal.parseGetArgs(location.href).mode,
+ hourglass;
+
+ e.stopPropagation();
+ e.preventDefault();
+
+ if (action == 'spam' && !modeParam) {
+ showDialogPopup();
+ } else {
+ sendModerateRequest();
+ }
+
+
+ function showDialogPopup() {
+ var popupElem = createPopup('<div class="b-popup-group"><div class="b-popup-row b-popup-row-head"><strong>' + getLocalizedStr('comment.mark.spam.title', comUser) + '</strong></div><div class="b-popup-row">' + getLocalizedStr('comment.mark.spam.subject', comUser) + '</div><div class="b-popup-row"><input type="button" class="spam-comment-button" value="OK"></div><div>', control, e, 'spamComment' + dItemid);
+
+ if (popupElem) {
+ popupElem.delegate('.spam-comment-button', 'click', function (e) {
+ e.preventDefault();
+ sendModerateRequest();
+ killPopup();
+ });
+ }
+ }
+
+ function sendModerateRequest() {
+ var bmlName = { 'screen': 'talkscreen', 'spam': 'delcomment' }[action],
+ postUrl = control.href.replace(new RegExp('.+' + bmlName + '\.bml'), LiveJournal.getAjaxUrl(bmlName)) + '&jsmode=1',
+ postParams = { 'confirm': 'Y', lj_form_auth: LJ_cmtinfo.form_auth };
+
hourglass = jQuery(e).hourglass()[0];
-
- var xhr = jQuery.post(postUrl + '&jsmode=1',
- {
- confirm: 'Y',
- lj_form_auth: LJ_cmtinfo.form_auth
- },
- function(json)
- {
+
+ if (action == 'spam') {
+ postUrl = (!isS1) ? postUrl.replace('id', 'talkid') : postUrl;
+ postParams.spam = 1;
+ }
+
+ jQuery.post(postUrl, postParams, function (json) {
tsInProg[dItemid] = 0;
- var comms_ary = [dItemid]
- var map_comms = function(id)
- {
- var i = -1, new_id;
- while(new_id = LJ_cmtinfo[id].rc[++i])
- {
- if (LJ_cmtinfo[new_id].full) {
- comms_ary.push(new_id);
- map_comms(String(new_id));
- }
- }
- }
- // check rc for no comments page
- if (LJ_cmtinfo[dItemid].rc) {
- if (/mode=(un)?freeze/.test(ae.href)) {
- map_comms(dItemid);
- }
- var ids = '#ljcmt' + comms_ary.join(',#ljcmt');
+ if (isS1) {
+ handleS1();
} else {
- var rpcRes;
- eval(json);
- updateLink(ae, rpcRes, ae.getElementsByTagName('img')[0]);
- // /tools/recent_comments.bml
- if (document.getElementById('ljcmtbar'+dItemid)) {
- var ids = '#ljcmtbar'+dItemid;
- }
- // ex.: portal/
- else {
- hourglass.hide();
- poofAt(pos);
- return;
- }
+ var ids = checkRcForNoCommentsPage(json);
+ handleS2(ids);
}
-
- if(isS1){
- var newNode, showExpand, j, children;
- var threadId = dItemid,
- threadExpanded = !!(LJ_cmtinfo[ threadId ].oldvars && LJ_cmtinfo[ threadId ].full);
- populateComments = function(result){
- for( var i = 0; i < result.length; ++i ){
- if( LJ_cmtinfo[ result[i].thread ].full ){
- showExpand = !( 'oldvars' in LJ_cmtinfo[ result[i].thread ]);
-
- //still show expand button if children comments are folded
- if( !showExpand ) {
- children = LJ_cmtinfo[ result[i].thread ].rc;
-
- for( j = 0; j < children.length; ++j ) {
- if( !( 'oldvars' in LJ_cmtinfo[ children[j] ] ) ) {
- showExpand = true;
- }
- }
+ });
+ }
+
+ function handleS1() {
+ var newNode, showExpand, j, children,
+ threadId = dItemid,
+ threadExpanded = !!(LJ_cmtinfo[ threadId ].oldvars && LJ_cmtinfo[ threadId ].full);
+ populateComments = function (result) {
+ for( var i = 0; i < result.length; ++i ){
+ if( LJ_cmtinfo[ result[i].thread ].full ){
+ showExpand = !( 'oldvars' in LJ_cmtinfo[ result[i].thread ]);
+
+ //still show expand button if children comments are folded
+ if( !showExpand ) {
+ children = LJ_cmtinfo[ result[i].thread ].rc;
+
+ for( j = 0; j < children.length; ++j ) {
+ if( !( 'oldvars' in LJ_cmtinfo[ children[j] ] ) ) {
+ showExpand = true;
}
-
- newNode = ExpanderEx.prepareCommentBlock(
- result[i].html,
- result[ i ].thread,
- showExpand
- );
-
- setupAjax( newNode[0], isS1 );
- jQuery("#ljcmtxt" + result[i].thread).replaceWith( newNode );
}
}
- hourglass.hide();
- poofAt(pos);
- };
-
- getThreadJSON(threadId, function(result) {
- //if comment is expanded we need to fetch it's collapsed state additionally
- if( threadExpanded && LJ_cmtinfo[ threadId ].oldvars.full )
- {
- getThreadJSON( threadId, function(result2){
- ExpanderEx.Collection[ threadId ] = ExpanderEx.prepareCommentBlock( result2[0].html, threadId, true ).html();
- populateComments( result );
- }, true, true );
+
+ if (!result[i].html) {
+ removeEmptyMarkup(result[i].thread);
+ }
+
+ newNode = ExpanderEx.prepareCommentBlock(
+ result[i].html || '',
+ result[i].thread || '',
+ showExpand
+ );
+
+ setupAjax( newNode[0], isS1 );
+
+ jQuery("#ljcmtxt" + result[i].thread).replaceWith( newNode );
}
- else
- populateComments( result );
- }, false, !threadExpanded);
+ }
+ hourglass.hide();
+ poofAt(pos);
+ };
+
+ getThreadJSON(threadId, function (result) {
+ //if comment is expanded we need to fetch it's collapsed state additionally
+ if( threadExpanded && LJ_cmtinfo[ threadId ].oldvars.full )
+ {
+ getThreadJSON( threadId, function (result2) {
+ ExpanderEx.Collection[ threadId ] = ExpanderEx.prepareCommentBlock( result2[0].html, threadId, true ).html();
+ populateComments( result );
+ }, true, true );
}
+ else
+ populateComments( result );
+ }, false, !threadExpanded);
+ }
+
+ function handleS2(ids) {
+ // modified jQuery.fn.load
+ jQuery.ajax({
+ url: location.href,
+ type: 'GET',
+ dataType: 'html',
+ complete: function (res, status) {
+ // If successful, inject the HTML into all the matched elements
+ if (status == 'success' || status == 'notmodified') {
+ // Create a dummy div to hold the results
+ var nodes = jQuery('<div/>')
+ // inject the contents of the document in, removing the scripts
+ // to avoid any 'Permission Denied' errors in IE
+ .append(res.responseText.replace(/<script(.|\s)*?\/script>/gi, ''))
+ // Locate the specified elements
+ .find(ids)
+ .each(function () {
+ var id = this.id.replace(/[^0-9]/g, '');
+ if (LJ_cmtinfo[id].expanded) {
+ var expand = this.innerHTML.match(/Expander\.make\(.+?\)/)[0];
+ (function(){
+ eval(expand);
+ }).apply(document.createElement('a'));
+ } else {
+ jQuery('#' + this.id).replaceWith(this);
+ setupAjax(this, isS1);
+ }
+ });
+ hourglass.hide();
+ poofAt(pos);
+ }
+ }
+ });
+ }
+
+ function checkRcForNoCommentsPage() {
+ var commsArray = [ dItemid ], ids;
+
+ // check rc for no comments page
+ if (LJ_cmtinfo[dItemid].rc) {
+ if (/mode=(un)?freeze/.test(control.href)) {
+ mapComms(dItemid);
+ }
+ ids = '#ljcmt' + commsArray.join(',#ljcmt');
+ } else {
+ var rpcRes;
+ eval(json);
+ updateLink(control, rpcRes, control.getElementsByTagName('img')[0]);
+ // /tools/recent_comments.bml
+ if (document.getElementById('ljcmtbar'+dItemid)) {
+ ids = '#ljcmtbar' + dItemid;
+ }
+ // ex.: portal/
else {
- // modified jQuery.fn.load
- jQuery.ajax({
- url: location.href,
- type: 'GET',
- dataType: 'html',
- complete: function(res, status) {
- // If successful, inject the HTML into all the matched elements
- if (status == 'success' || status == 'notmodified') {
- // Create a dummy div to hold the results
- var nodes = jQuery('<div/>')
- // inject the contents of the document in, removing the scripts
- // to avoid any 'Permission Denied' errors in IE
- .append(res.responseText.replace(/<script(.|\s)*?\/script>/gi, ''))
- // Locate the specified elements
- .find(ids)
- .each(function(){
- var id = this.id.replace(/[^0-9]/g, '');
- if (LJ_cmtinfo[id].expanded) {
- var expand = this.innerHTML.match(/Expander\.make\(.+?\)/)[0];
- (function(){
- eval(expand);
- }).apply(document.createElement('a'));
- } else {
- jQuery('#'+this.id).replaceWith(this);
- setupAjax(this, isS1);
- }
- });
- hourglass.hide();
- poofAt(pos);
- }
- }
- });
+ hourglass.hide();
+ poofAt(pos);
+ return;
}
}
- );
+
+ return ids;
+
+ function mapComms(id) {
+ var i = -1, newId;
+
+ while (newId = LJ_cmtinfo[id].rc[++i]) {
+ if (LJ_cmtinfo[newId].full) {
+ commsArray.push(newId);
+ mapComms(String(newId));
+ }
+ }
+ }
+ }
return false;
}
}
+function removeEmptyMarkup(threadId) {
+ jQuery('#ljcmt' + threadId).remove();
+}
+
function setupAjax (node, isS1) {
var links = node ? node.getElementsByTagName('a') : document.links,
rex_id = /id=(\d+)/,
@@ -550,7 +701,7 @@
var id = reMatch[1];
if (!document.getElementById('ljcmt' + id)) continue;
- ae.onclick = createModerationFunction(ae, id, isS1);
+ ae.onclick = createModerationFunction(ae, id, isS1, 'screen');
} else if (ae.href.indexOf('delcomment.bml') != -1) {
if (LJ_cmtinfo && LJ_cmtinfo.disableInlineDelete) continue;
@@ -560,28 +711,34 @@
var id = reMatch[1];
if (!document.getElementById('ljcmt' + id)) continue;
- ae.onclick = createDeleteFunction(ae, id, isS1);
- }
+ if (ae.href.indexOf('spam=1') != -1) {
+ ae.onclick = createModerationFunction(ae, id, isS1, 'spam');
+ } else {
+ ae.onclick = createDeleteFunction(ae, id, isS1);
+ }
+ }
}
}
function getThreadJSON(threadId, success, getSingle)
{
var postid = location.href.match(/\/(\d+).html/)[1],
+ modeParam = LiveJournal.parseGetArgs(location.href).mode,
params = [
'journal=' + Site.currentJournal,
'itemid=' + postid,
'thread=' + threadId,
'depth=' + LJ_cmtinfo[ threadId ].depth
];
- if( getSingle)
+
+ if (getSingle)
params.push( 'single=1' );
+
+ if (modeParam)
+ params.push( 'mode=' + modeParam )
var url = LiveJournal.getAjaxUrl('get_thread') + '?' + params.join( '&' );
jQuery.get( url, success, 'json' );
}
jQuery(function(){setupAjax( false, ("is_s1" in LJ_cmtinfo ) )});
-
-DOM.addEventListener(document, 'click', docClicked);
-document.write("<style> div.ljcmtmanage { color: #000; background: #e0e0e0; border: 2px solid #000; padding: 3px; }</style>");
