您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Shows some goal information, progress, etc. on the dashboard
// ==UserScript== // @name MTurk Dashboard Goals // @version 0.72b // @description Shows some goal information, progress, etc. on the dashboard // @include https://www.mturk.com/mturk/dashboard // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_xmlhttpRequest // @copyright 2012+, Tjololo12 // @namespace https://gf.qytechs.cn/users/710 // ==/UserScript== // //GM_deleteValue('GOALS_goal_table'); var retryAttempts = '10'; var retryTime = '250'; var goalTableJson = []; if (GM_getValue('GOALS_goal_table')){ var goalStuff = GM_getValue('GOALS_goal_table'); goalTableJson = JSON.parse(goalStuff); if (Object.keys(goalTableJson).length == 0){ GM_deleteValue('GOALS_goal_table'); goalTableJson = []; } } var numEntries = (GM_getValue('GOALS_goal_table') ? Object.keys(goalTableJson).length : 0); var balance = 0; var refresh = false; if (!GM_getValue('GOALS_balance')){ balance = get_balance(); refresh = true; GM_setValue('GOALS_balance', balance); GM_setValue('GOALS_timestamp', new Date()); } else{ if (GM_getValue('GOALS_timestamp')){ console.log(datediff("minutes", GM_getValue('GOALS_timestamp'), "")+" timestamp: "+GM_getValue('GOALS_timestamp')); if (datediff("minutes", GM_getValue('GOALS_timestamp'), "") > 1){ balance = get_balance(); refresh = true; GM_setValue('GOALS_balance', balance); GM_setValue('GOALS_timestamp', new Date()); } else balance = GM_getValue('GOALS_balance'); } else{ balance = get_balance(); refresh = true; GM_setValue('GOALS_balance', balance); GM_setValue('GOALS_timestamp', new Date()); } } var cells= document.getElementsByClassName('metrics-table-first-value'); var contains = false; var approvedHits = 0; for (var i = 0, len = cells.length; i < len; ++i) { if(cells[i].innerHTML.indexOf("Today's Projected Earnings") != -1) { console.log("Pending earnings found: "+cells[i].parentNode.getElementsByTagName('td')[1].innerHTML.replace(/[^0-9\.]/g, '')); GM_setValue('GOALS_today_pending', cells[i].parentNode.getElementsByTagName('td')[1].innerHTML.replace(/[^0-9\.]/g, '')); contains = true; } if(cells[i].innerHTML.indexOf("Approved HITs") != -1) { console.log("Approved HITs found: "+cells[i].parentNode.getElementsByTagName('td')[1].innerHTML.replace(/[^0-9\.]/g, '')); approvedHits = parseFloat(cells[i].parentNode.getElementsByTagName('td')[1].innerHTML.replace(/[^0-9\.]/g, '')); } } console.log("Data "+(refresh ? "" : "not ")+"refreshed"); //Compatibility for converting old entries if (!GM_getValue('GOALS_converted')){ for (var key in goalTableJson){ //if (!goalTableJson[key]['start']) goalTableJson[key]['start'] = approvedHits - balance; console.log(goalTableJson[key]['start']); } var goalString = JSON.stringify(goalTableJson); GM_setValue('GOALS_goal_table', goalString); goalTableJson = GM_getValue('GOALS_goal_table'); console.log("Data converted"); } var TEMPLATE = "{name} | {amount} | {days} | {percent}"; if (GM_getValue('GOALS_export_template')) TEMPLATE = GM_getValue('GOALS_export_template'); var EDIT = false; function fetchData() { var timer; if (typeof numCon === 'undefined') { var numCon = 0; } else if (numCon > retryAttempts) { throw new Error("Could not get data."); } GM_xmlhttpRequest({ method: "GET", url: "https://www.mturk.com/mturk/youraccount", onload: function (response) { // Get balance var reBal = /(\$\d+,?.?\d+,?.?\d+,?.?\d?\d?)/; var balance = response.responseText.match(reBal); if (balance['0']) { GM_setValue('GOAL_AMZ_Balance', balance['0'].substr(1)); return balance['0'].substr(1); } else { GM_setValue('GOAL_AMZ_Balance', 0); return 0; } } }); numCon++; } /* ----------------------------------------------------------------------------------- */ function get_balance() { var retval = fetchData(); if (GM_getValue('GOAL_AMZ_Balance')) { return GM_getValue('GOAL_AMZ_Balance'); } else return retval; } function saveOrder_func(){ var goalTable = document.getElementById('goal_table'); var rows = goalTable.rows; var goalJson = (goalTableJson ? goalTableJson : []); var newJson = []; for (var i=0; i<rows.length; i++) { if (goalJson[rows[i].id.replace(/[^0-9\.]/g, '')]) newJson.push(goalJson[rows[i].id.replace(/[^0-9\.]/g, '')]); } goalTableJson = newJson; var goalString = JSON.stringify(newJson); //console.log(goalString); GM_setValue('GOALS_goal_table', goalString); document.getElementById('hide_button').click(); } function addRow_func(){ //console.log("addRow"); //var new_row = document.createElement('tr'); var checkbox = document.createElement('td'); var goal_name = document.createElement('td'); var type_name = document.createElement('td'); var goal_amount = document.createElement('td'); var date = document.createElement('td'); var order = document.createElement('td'); goalTable = document.getElementById('goal_table'); var element1 = document.createElement("input"); var element2 = document.createElement("input"); var element3 = document.createElement("input"); var element4 = document.createElement("input"); var element5 = document.createElement("select"); var element6 = document.createElement("select"); var tempNum = numEntries; var nameId = "newName_"+tempNum; var amountId = "newAmount_"+tempNum; var dateId = "newDate_"+tempNum; var checkId = "radio_"+tempNum; var typeId = "type_"+tempNum; var typeCellId = "newType_"+tempNum; var orderId = "order_"+tempNum; var orderCellId = "newOrder_"+tempNum; goal_name.setAttribute('id', nameId); goal_amount.setAttribute('id', amountId); date.setAttribute('id', dateId); type_name.setAttribute('id', typeCellId); order.setAttribute('id', orderCellId); element1.type = "radio"; element1.disabled = true; element1.setAttribute('id', checkId); checkbox.appendChild(element1); element2.type = "text"; element2.value = "What is it?"; element2.setAttribute('onFocus','if (this.value == \'What is it?\') this.value=\'\''); element2.id = "name_"+tempNum; goal_name.appendChild(element2); element3.type = "text"; element3.value = "$x,xxx.xx"; element3.setAttribute('onFocus', 'if (this.value == \'$x,xxx.xx\') this.value=\'\''); element3.id = "amount_"+tempNum; goal_amount.appendChild(element3); element4.type = "text"; element4.value = "mm/dd/yyyy"; element4.setAttribute('onFocus', 'if (this.value == \'mm/dd/yyyy\') this.value=\'\''); element4.id = "date_"+tempNum; date.appendChild(element4); element5.setAttribute('id', typeId); var option = document.createElement('option'); option.value = 'normal'; option.appendChild(document.createTextNode('Normal')); element5.appendChild(option); option = document.createElement('option'); option.value = 'day'; option.appendChild(document.createTextNode('Daily Goal')); element5.appendChild(option); type_name.appendChild(element5); for (var i = 0; i < numEntries + 1; i++){ option = document.createElement('option'); option.value = i; option.appendChild(document.createTextNode(i+1)); if (i == numEntries) option.setAttribute("selected", "selected"); element6.appendChild(option); } order.appendChild(element6); element6.setAttribute('id', orderId); if (!GM_getValue('GOALS_goal_table') && document.getElementById('noContentRow')) goalTable.deleteRow(1); var new_row = goalTable.insertRow(++numEntries); //goalTable.appendChild(new_row) new_row.setAttribute("NoDrag", 1); new_row.appendChild(goal_name); new_row.appendChild(type_name); new_row.appendChild(goal_amount); new_row.appendChild(date); new_row.appendChild(checkbox); new_row.appendChild(order); } function validate_date(input) { var date = input.value; if (!date || date == "mm/dd/yyyy") return true; if (date.match(/^[01]\d\/[0123]\d\/20\d\d$/) != null) { var d = date.split('\/'); date = d[2] + '-' + d[0] + '-' + d[1]; input.value = date; } if (date.match(/^$|^20\d\d\-[01]\d\-[0123]\d$/) != null) { input.style.backgroundColor = 'white'; return true; } input.style.backgroundColor = 'pink'; return false; } function validate_amount(input) { var amount = input.value; if (amount.match(/^\$?(\d+,?)+(\.\d\d)?$/)){ return true; } else return false; } function validate_type(input) { var type = input.value; if (type == "day") { var cells= document.getElementsByClassName('metrics-table-first-value'); var contains = false; for (var i = 0, len = cells.length; i < len; ++i) { if(cells[i].innerHTML.indexOf("Today's Projected Earnings") != -1) { console.log("Pending earnings found: "+cells[i].parentNode.getElementsByTagName('td')[1].innerHTML.replace(/[^0-9\.]/g, '')); GM_setValue('GOALS_today_pending', cells[i].parentNode.getElementsByTagName('td')[1].replace(/[^0-9\.]/g, '')); contains = true; } } if (!contains) alert("Daily goals require the installation of the \"Today's Projected Earnings\" script from userscripts.org."); return contains; } else return true; } function save_values(){ // try{ var jsonObj = []; for (var i = (GM_getValue('GOALS_goal_table') ? Object.keys(goalTableJson).length : 0); i <= numEntries-1; i++) { var nameCellId = "newName_"+i; var amountCellId = "newAmount_"+i; var dateCellId = "newDate_"+i; var typeCellId = "newType_"+i; var orderCellId = "newOrder_"+i; var nameId = "name_"+i; var amountId = "amount_"+i; var dateId = "date_"+i; var checkId = "radio_"+i; var typeId = "type_"+i; var orderId = "order_"+i; var name = document.getElementById(nameId); var amount = document.getElementById(amountId); var date = document.getElementById(dateId); var type = document.getElementById(typeId); var order = document.getElementById(orderId); var nameVal = name.value; var amountVal = amount.value.replace("$",""); amountVal = amountVal.replace(",",""); var tempAmountVal = amount.value; var dateVal = date.value; var typeVal = type.options[type.selectedIndex].value; var orderVal = order.options[order.selectedIndex].value; if (typeVal == 'day') { var tempDate = new Date(); var months = parseInt(tempDate.getMonth()); var days = parseInt(tempDate.getDate()); var years = parseInt(tempDate.getFullYear()); months += 1; days += 1; if (months.length == 1) months = "0"+months; if (days.length == 1) days = "0"+days; var dateString = months + "/" + days + "/" + years; console.log(dateString); dateVal = dateString; } if (!validate_date(date)){ alert("Invalid date format! Please use mm/dd/yyyy or yyyy-mm-dd"); return false; } if (!validate_amount(amount)){ alert("Invalid amount format! Please use $x,xxx.xx or x,xxx.xx or xxxx.xx"); return false; } if (!validate_type(typeVal)){ return false; } var nameCell = document.getElementById(nameCellId); var amountCell = document.getElementById(amountCellId); var dateCell = document.getElementById(dateCellId); var typeCell = document.getElementById(typeCellId); var orderCell = document.getElementById(orderCellId); var startVal = approvedHits; jsonObj[i] = {'name':nameVal, 'amount':amountVal, 'date':(dateVal == "mm/dd/yyyy" ? null : dateVal), 'type':(typeVal == 'normal' ? null : typeVal), 'start':startVal}; nameCell.removeChild(name); nameCell.textContent = nameVal; amountCell.removeChild(amount); amountCell.textContent = ""+parseFloat(tempAmountVal).formatMoney(2); dateCell.removeChild(date); dateCell.textContent = (dateVal != "mm/dd/yyyy" ? dateVal : ""); typeCell.removeChild(type); typeCell.textContent = (typeVal == 'normal' ? "Normal" : typeVal); orderCell.removeChild(order); orderCell.textContent = orderVal; document.getElementById(checkId).disabled = false; } var goalJson = (goalTableJson ? goalTableJson : []); for (var key in jsonObj) goalJson.splice(parseInt(orderVal)-1, 0, jsonObj[key]); goalTableJson = goalJson; var goalString = JSON.stringify(goalJson); //console.log(goalString); GM_setValue('GOALS_goal_table', goalString); toggleGoalDiv(); toggleGoalDiv(); return true; // } // catch (err){ // console.log(err); // return false; // } } function updateDate(key) { var tempDate = new Date(); var months = parseInt(tempDate.getMonth()); var days = parseInt(tempDate.getDate()); var years = parseInt(tempDate.getFullYear()); var numDays = new Date(years, months, 0).getDate(); months = (months + 1 > 12 ? 1 : (days + 1 > numDays ? months + 2 : months + 1)); days = (days + 1 > numDays ? 1 : days + 1); if (months.length == 1) months = "0"+months; if (days.length == 1) days = "0"+days; var dateString = months + "/" + days + "/" + years; console.log(dateString); var goalDate = goalTableJson[key]['date']; if (goalDate != dateString){ goalTableJson[key]['date'] = dateString; var goalString = JSON.stringify(goalTableJson); GM_setValue('GOALS_goal_table', goalString); } } Number.prototype.formatMoney = function(c, d, t){ var n = this, c = isNaN(c = Math.abs(c)) ? 2 : c, d = d == undefined ? "." : d, t = t == undefined ? "," : t, s = n < 0 ? "-$" : "$", i = parseFloat(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.split('.')[0].length) > 3 ? j % 3 : 0; return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c && i%1 == 0 ? d + Math.abs(n - i).toFixed(c).slice(2) : ""); }; function datediff(interval,date1,laterDate) { var second=1000, minute=second*60, hour=minute*60, day=hour*24, week=day*7; date1 = new Date(date1); var date2 = (laterDate ? new Date(date2) : new Date()); var timediff = date2 - date1; if (isNaN(timediff)) return ""; switch (interval) { case "years": return date2.getFullYear() - date1.getFullYear(); case "months": return ( ( date2.getFullYear() * 12 + date2.getMonth() ) - ( date1.getFullYear() * 12 + date1.getMonth() ) ); case "weeks" : return Math.floor(timediff / week); case "days" : return Math.floor(timediff / day); case "hours" : return Math.floor(timediff / hour); case "minutes": return Math.floor(timediff / minute); case "seconds": return Math.floor(timediff / second); case "all": var retVal = {}; retVal["years"] = date2.getFullYear() - date1.getFullYear(); retVal["months"] = ( date2.getFullYear() * 12 + date2.getMonth() )-( date1.getFullYear() * 12 + date1.getMonth() ) retVal["weeks"] = Math.floor(timediff/week); retVal["days"] = Math.floor(timediff/day); retVal["hours"] = Math.floor(timediff/hour); retVal["minutes"] = Math.floor(timediff/minute); retVal["seconds"] = Math.floor(timediff/second); return retVal; case "cmp": return date1 <= date2; default: return undefined; } } function AddAfter(rowId){ var target = document.getElementById(rowId); var newElement = document.createElement('tr'); target.parentNode.insertBefore(newElement, target.nextSibling ); return newElement; } function deleteGoal(key){ var rowKey = "row_"+key+"_goalTable"; //console.log(rowKey); var target = document.getElementById(rowKey); //target.parentNode.remove(target); target.remove(); var newJson = []; for (var oldKey in goalTableJson){ if (oldKey == key) console.log("found old key, removing"); else newJson.push(goalTableJson[oldKey]); } //console.log(newJson); //goalTableJson.splice(key,1); numEntries--; GM_setValue('GOALS_goal_table', JSON.stringify(newJson)); goalTableJson = newJson; } function showInfo(key){ //console.log(goalTableJson[key]); var itemButton = document.getElementById("button_"+key); var item = goalTableJson[key]; var infoDiv = document.createElement('div'); var timeInfo = (item['date'] ? datediff("all", item['date'], "") : ""); var rowKey = "row_"+key; var divRow = AddAfter(rowKey); rowKey += "_info"; var divCell = document.createElement('td'); var amountInt = parseFloat(item['amount']); var amountStart = parseFloat(item['start']); var diff = approvedHits - amountStart; var pendingSum = GM_getValue('GOALS_today_pending'); divCell.style.cellPadding = '10px'; divCell.setAttribute('align', 'center'); divCell.setAttribute('id', rowKey); divCell.addEventListener("click", function() { var target = document.getElementById(rowKey); target.parentNode.remove(target);}, false); divRow.appendChild(divCell); divCell.setAttribute('colspan', '5'); divCell.appendChild(infoDiv); infoDiv.style.width = "90%"; infoDiv.style.backgroundColor = "#E9D99D"; infoDiv.setAttribute('align', 'left'); var progress = ((item['type'] == 'day' ? pendingSum : diff) / amountInt); progress = progress * 100; var progFull = Math.round(progress*100)/100; var complete = (progFull > 100 ? "Complete :D" : 100-progFull+"%"); var difference = amountInt - (item['type'] == 'day' ? pendingSum : balance); var today = new Date(); var dd = today.getDate(); var mm = today.getMonth()+1; //January is 0! var yyyy = today.getFullYear(); if(dd<10){dd='0'+dd} if(mm<10){mm='0'+mm} today = mm+'/'+dd+'/'+yyyy; var todaysDate = today; var infoText = "As of today, "+todaysDate+", your goal of "+amountInt.formatMoney(2)+(progFull > 100 ? " has " : " has not ")+"been reached"; if (progFull < 100){ if (!datediff("cmp", item['date'], "")) { infoText += ". You are "+complete+" away from your goal, and need to make an additional "+difference.formatMoney(2)+" to reach it."; if (timeInfo){ var perHour = (timeInfo["hours"]*-1 > 0 ? difference / timeInfo["hours"] * -1 : 0); var perMinute = (timeInfo["minutes"]*-1 > 0 ? difference / timeInfo["minutes"] * -1 : 0); var perDay = (timeInfo["days"]*-1 > 0 ? difference / timeInfo["days"] * -1 : 0); var perMonth = (timeInfo["months"]*-1 > 0 ? difference / timeInfo["months"] * -1 : 0); var perWeek = (timeInfo["weeks"]*-1 > 0 ? difference / timeInfo["weeks"] * -1 : 0); infoText += " This means you need to make:"; var list = document.createElement('ul'); var monthElement = document.createElement('li'); var weekElement = document.createElement('li'); var dayElement = document.createElement('li'); var hourElement = document.createElement('li'); var minuteElement = document.createElement('li'); monthElement.innerHTML = "$" + perMonth.toFixed(4) + " per month"; weekElement.innerHTML = "$" + perWeek.toFixed(4) + " per week"; dayElement.innerHTML = "$" + perDay.toFixed(4) + " per day"; hourElement.innerHTML = "$" + perHour.toFixed(4) + " per hour"; minuteElement.innerHTML = "$" + perMinute.toFixed(4) + " per minute"; if (!perMonth == 0 && item['type'] != 'day') list.appendChild(monthElement); if (!perWeek == 0 && item['type'] != 'day') list.appendChild(weekElement); if (!perDay == 0 && item['type'] != 'day') list.appendChild(dayElement); if (!perHour == 0) list.appendChild(hourElement); if (!perMinute == 0) list.appendChild(minuteElement); else{ var tempElement = document.createElement('li'); tempElement.innerHTML = "You have less than a minute to make "+difference.formatMoney(2)+"! Can you make it?!"; list.appendChild(tempElement); } infoDiv.textContent = infoText; infoDiv.appendChild(list); } } else{ infoText += "...unfortunately, the deadline has passed. You were "+difference.formatMoney(2)+" away from meeting your goal :("; infoDiv.textContent = infoText; } if (!timeInfo) infoDiv.textContent = infoText; } else{ infoText += ", congratulations! Your goal of "+item['name']+" is within reach, all you need to do is withdraw the money. Visit your account information screen to do so!"; infoDiv.textContent = infoText; } } function toggleGoalDiv(){ var target = document.getElementById('goal_div'); if (!target){ //console.log("created div"); showAddGoalTable(); } else target.remove(); } function toggleExportDiv(){ var target = document.getElementById('export_div'); if (!target){ //console.log("created div"); showExportDiv(); } else target.remove(); } var goalTableJson = ""; if (GM_getValue('GOALS_goal_table')){ var goalStuff = GM_getValue('GOALS_goal_table'); goalTableJson = JSON.parse(goalStuff); } var numEntries = (GM_getValue('GOALS_goal_table') ? Object.keys(goalTableJson).length : 0); function apply_template() { var txt = TEMPLATE; var outString = ""; var vars = ['name', 'amount', 'days', 'percent', 'type']; var pendingSum = GM_getValue('GOALS_today_pending'); for (var key in goalTableJson){ var tempTemp = txt; for (var i=0; i<vars.length; i++) { t = new RegExp('\{' + vars[i] + '\}', 'g'); if (vars[i] == 'name') tempTemp = tempTemp.replace(t, goalTableJson[key][vars[i]]); else if (vars[i] == 'amount') tempTemp = tempTemp.replace(t, parseFloat(goalTableJson[key][vars[i]]).formatMoney(2)); else if (vars[i] == 'percent'){ var progress = ((goalTableJson[key]['type'] == 'day' ? pendingSum : balance) / amountInt); progress = progress * 100; var progFull = Math.round(progress*100)/100; tempTemp = tempTemp.replace(t, (progFull >= 100 ? "Complete :D" : progFull+"%")); } else if (vars[i] == 'days'){ var amountInt = parseFloat(goalTableJson[key]['amount']); var progress = ((goalTableJson[key]['type'] == 'day' ? pendingSum : balance) / amountInt); progress = progress * 100; var progFull = Math.round(progress*100)/100; console.log(progFull); var daysDiff = (progFull >= 100 ? "Complete :D" : (goalTableJson[key]['type'] == 'day' ? "Daily Goal" : (goalTableJson[key]['date'] ? datediff("days", goalTableJson[key]['date'], "") * -1 : "No end date given"))); tempTemp = tempTemp.replace(t, daysDiff); } else if (vars[i] == 'type') { var replaceString = (goalTableJson[key]['type'] ? (goalTableJson[key]['type'] == 'day' ? "Daily Goal" : "Normal Goal") : (goalTableJson[key]['date'] ? "Deadline" : "No Deadline")); tempTemp = tempTemp.replace(t, replaceString); } } outString += tempTemp + "\n"; } return outString; } function showAddGoalTable(){ var goal_div = document.createElement('div'); var goalTable = document.createElement('table'); var header_row = document.createElement('tr'); var typeCell = document.createElement('td'); var checkbox = document.createElement('td'); var goal_name = document.createElement('td'); var goal_amount = document.createElement('td'); var date = document.createElement('td'); var order = document.createElement('td'); var radioNames = []; goal_div.style.position = 'fixed'; goal_div.style.left = '20%'; goal_div.style.right = '20%'; goal_div.style.top = '300px'; goal_div.style.padding = '5px'; goal_div.style.border = '2px solid black'; goal_div.style.backgroundColor = 'white'; goal_div.setAttribute('id', 'goal_div'); goalTable.style.margin = '0 auto 0 auto'; goalTable.style.width = '90%'; goalTable.setAttribute('id', 'goal_table'); checkbox.textContent = 'Delete?'; typeCell.textContent = 'Type'; goal_name.textContent = 'Goal Name'; goal_amount.textContent = 'Goal Amount'; date.textContent = 'Date (optional)'; order.textContent = 'Goal fill order'; goalTable.appendChild(header_row); header_row.style.backgroundColor = '#7fb4cf';//'#7fb4cf'; header_row.appendChild(goal_name); header_row.appendChild(typeCell); header_row.appendChild(goal_amount); header_row.appendChild(date); header_row.appendChild(checkbox); header_row.appendChild(order); header_row.setAttribute("NoDrag", 1); if (!goalTableJson || goalTableJson.length == 0){ var contentRow1 = document.createElement('tr'); var noContent = document.createElement('td'); noContent.textContent = 'Uh-oh, it looks like you haven\'t set any goals. Click the \'Add goal\' button below to add one!'; noContent.setAttribute('colspan', '5'); contentRow1.setAttribute('id', 'noContentRow'); goalTable.appendChild(contentRow1); contentRow1.appendChild(noContent); } else{ var goalString = goalTableJson; for (var key in goalString){ var new_row = document.createElement('tr'); var checkbox = document.createElement('td'); var type = document.createElement('td'); var goal_name = document.createElement('td'); var goal_amount = document.createElement('td'); var date = document.createElement('td'); var order = document.createElement('td'); order.textContent = parseInt(key)+1; var rowKey = "row_"+key+"_goalTable"; new_row.setAttribute('id', rowKey); var element1 = document.createElement("input"); element1.type = "radio"; element1.id = key ; checkbox.appendChild(element1); id = "radio_"+key; radioNames.push(id); element1.setAttribute('id', id); goal_name.textContent = goalString[key]['name']; type.textContent = (goalString[key]['type'] ? goalString[key]['type'] : (goalString[key]['date'] ? "Deadline" : "Normal")); goal_amount.textContent = parseFloat(goalString[key]['amount']).formatMoney(2); date.textContent = goalString[key]['date']; goalTable.appendChild(new_row); new_row.appendChild(goal_name); new_row.appendChild(type); new_row.appendChild(goal_amount); new_row.appendChild(date); new_row.appendChild(checkbox); new_row.appendChild(order); } } var new_row = document.createElement('tr'); var b1 = document.createElement('td'); var b2 = document.createElement('td'); var b3 = document.createElement('td'); var b4 = document.createElement('td'); var b5 = document.createElement('td'); var add_row = document.createElement('button'); var delete_all = document.createElement('button'); var save_button = document.createElement('button'); var hide_button = document.createElement('button'); var reorder_button = document.createElement('button'); add_row.textContent = ' Add goal '; add_row.setAttribute('id', 'add_goal'); add_row.style.height = '18px'; add_row.style.width = '100px'; add_row.style.fontSize = '10px'; add_row.style.paddingLeft = '3px'; add_row.style.paddingRight = '3px'; add_row.style.backgroundColor = 'white'; add_row.style.marginLeft = '5px'; add_row.title = 'Add a new goal'; b1.appendChild(add_row); b1.setAttribute('aligh','left'); delete_all.textContent = ' Delete '; delete_all.setAttribute('id', 'delete_all'); delete_all.style.height = '18px'; delete_all.style.width = '100px'; delete_all.style.fontSize = '10px'; delete_all.style.paddingLeft = '3px'; delete_all.style.paddingRight = '3px'; delete_all.style.backgroundColor = 'white'; delete_all.style.marginLeft = '5px'; delete_all.title = 'Delete all goals from storage'; b2.appendChild(delete_all); b2.setAttribute('align','center'); save_button.textContent = 'Save'; save_button.setAttribute('id', 'save_button'); save_button.style.height = '18px'; save_button.style.width = '100px'; save_button.style.fontSize = '10px'; save_button.style.paddingLeft = '3px'; save_button.style.paddingRight = '3px'; save_button.style.backgroundColor = 'white'; save_button.style.marginLeft = '5px'; save_button.title = 'Save goals in storage'; b3.appendChild(save_button); b3.setAttribute('align','center'); hide_button.textContent = 'Cancel'; hide_button.setAttribute('id', 'hide_button'); hide_button.style.height = '18px'; hide_button.style.width = '100px'; hide_button.style.fontSize = '10px'; hide_button.style.paddingLeft = '3px'; hide_button.style.paddingRight = '3px'; hide_button.style.backgroundColor = 'white'; hide_button.style.marginLeft = '5px'; hide_button.title = 'Hide div'; b4.appendChild(hide_button); b4.setAttribute('align','center'); reorder_button.textContent = 'Reorder'; reorder_button.setAttribute('id', 'reorder_button'); reorder_button.style.height = '18px'; reorder_button.style.width = '100px'; reorder_button.style.fontSize = '10px'; reorder_button.style.paddingLeft = '3px'; reorder_button.style.paddingRight = '3px'; reorder_button.style.backgroundColor = 'white'; reorder_button.style.marginLeft = '5px'; reorder_button.title = 'Reorder Goals'; b5.appendChild(reorder_button); b5.setAttribute('align','right'); new_row.setAttribute("NoDrag", 1); new_row.appendChild(b1); new_row.appendChild(b2); new_row.appendChild(b3); new_row.appendChild(b4); new_row.appendChild(b5); goalTable.appendChild(new_row); delete_all.addEventListener("click", function() {if (confirm("Are you sure you want to delete all goals forever?")) GM_deleteValue('GOALS_goal_table'); goalTableJson = []; toggleGoalDiv(); toggleGoalDiv();}, false); add_row.addEventListener("click", function() {addRow_func();}, false); save_button.addEventListener("click", function() {if (save_values()) alert("Values successfully saved!"); else alert("Some error occurred :(");}, false); hide_button.addEventListener("click", function() {numEntries = (GM_getValue('GOALS_goal_table') ? Object.keys(goalTableJson).length : 0); toggleGoalDiv(); addGoalInformation();}, false); reorder_button.addEventListener("click", function() {saveOrder_func();}, false); goal_div.appendChild(goalTable); document.body.insertBefore(goal_div,document.getElementsByClassName('footer_separator')[0]); goal_div.style.display = 'block'; for (var i = 0; i < radioNames.length; i++) { (function (i) { document.getElementById(radioNames[i]).addEventListener("click", function() {if (confirm("Are you sure you want to delete that goal?")) deleteGoal(i);}, false); })(i); } var goalTable = document.getElementById('goal_table'); console.log(goalTable); var tableDnD = new TableDnD(); tableDnD.init(goalTable); } function edit_func() { var textarea = document.getElementById('export_text_area'); if (EDIT == true) { EDIT = false; TEMPLATE = textarea.value; GM_setValue('GOALS_export_template', TEMPLATE); document.getElementById('edit_button').textContent = 'Edit Template'; textarea.value = apply_template(); textarea.readOnly = true; } else { EDIT = true; document.getElementById('edit_button').textContent = 'Show Changes'; textarea.textContent = TEMPLATE; textarea.readOnly = false; } } function showExportDiv(){ var exportDiv = document.createElement('div'); var textarea = document.createElement('textarea'); exportDiv.style.position = 'fixed'; exportDiv.style.width = '500px'; exportDiv.style.height = '235px'; exportDiv.style.left = '50%'; exportDiv.style.right = '50%'; exportDiv.style.margin = '-250px 0px 0px -250px'; exportDiv.style.top = '300px'; exportDiv.style.padding = '5px'; exportDiv.style.border = '2px'; exportDiv.style.backgroundColor = 'black'; exportDiv.style.color = 'white'; exportDiv.style.zIndex = '100'; exportDiv.setAttribute('id', 'export_div'); textarea.style.padding = '2px'; textarea.style.width = '500px'; textarea.style.height = '200px'; textarea.title = 'Template accepts {name}, {amount}, {days}, {type}, and {percent}'; textarea.setAttribute('id', 'export_text_area'); textarea.textContent = apply_template(); exportDiv.textContent = 'Press Ctrl+C to copy to clipboard. Click exit to close.'; exportDiv.style.fontSize = '12px'; exportDiv.appendChild(textarea); var edit_button = document.createElement('button'); var hideButton = document.createElement('button'); edit_button.textContent = 'Edit Template'; edit_button.setAttribute('id', 'edit_button'); edit_button.style.height = '18px'; edit_button.style.width = '100px'; edit_button.style.fontSize = '10px'; edit_button.style.paddingLeft = '3px'; edit_button.style.paddingRight = '3px'; edit_button.style.backgroundColor = 'white'; hideButton.textContent = 'Exit'; hideButton.setAttribute('id', 'hide_export_button'); hideButton.style.height = '18px'; hideButton.style.width = '100px'; hideButton.style.fontSize = '10px'; hideButton.style.paddingLeft = '3px'; hideButton.style.paddingRight = '3px'; hideButton.style.backgroundColor = 'white'; exportDiv.appendChild(edit_button); exportDiv.appendChild(hideButton); hideButton.addEventListener("click", function() {toggleExportDiv();}, false); edit_button.addEventListener("click", function() {edit_func();}, false); document.body.insertBefore(exportDiv,document.getElementsByClassName('footer_separator')[0]); textarea.focus(); textarea.select(); textarea.readOnly = true; } function refresh_func(){ console.log("Debug refresh started..."); balance = get_balance(); GM_setValue('GOALS_balance', balance); console.log("Balance: "+balance); goalTableJson = JSON.parse(GM_getValue('GOALS_goal_table')); console.log("JSON:"); console.log(""+JSON.stringify(goalTableJson)); console.log("Debug refresh ended. Please reload."); addGoalInformation(); } if (window.location.href == "https://www.mturk.com/mturk/dashboard") { addGoalInformation(); } function addGoalInformation(){ if (!document.getElementById('primary_goal_table')){ var footer = document.getElementsByClassName('footer_separator')[0]; if (footer == null) return; var extra_table = document.createElement('table'); extra_table.width = '700'; extra_table.style.boder = '1px solid black'; extra_table.align = 'center'; extra_table.cellSpacing = '0px'; extra_table.cellPadding = '0px'; extra_table.setAttribute('id', 'primary_goal_table'); var row1 = document.createElement('tr'); var row2 = document.createElement('tr'); var td1 = document.createElement('td'); var td2 = document.createElement('td'); var content_td = document.createElement('td'); var whatsthis = document.createElement('a'); var goals_button = document.createElement('button'); var export_button = document.createElement('button'); var force_refresh_button = document.createElement('button'); //export_button.addEventListener("click", export_func(), false); row1.style.height = '25px'; row1.setAttribute('id', 'goals_header_row'); td1.setAttribute('class', 'white_text_14_bold'); td1.style.backgroundColor = '#7fb4cf';//'#7fb4cf'; td1.style.paddingLeft = '10px'; td1.innerHTML = ' Goals '; content_td.setAttribute('class', 'container-content'); content_td.setAttribute('colspan', '2'); whatsthis.href = 'javascript:alert(\'Allows you to define custom goals, based on the information that you give it. For more information, click the goal name. Click the info pane to close.\')'; whatsthis.setAttribute('class', 'whatis'); whatsthis.textContent = '(What\'s this?)'; goals_button.setAttribute('class', 'goals_button'); goals_button.textContent = 'Define Goals'; export_button.setAttribute('class', 'export_button'); export_button.textContent = 'Export Data'; force_refresh_button.setAttribute('class', 'refresh_button'); force_refresh_button.textContent = "Refresh"; td2.setAttribute('class', 'white_text_14_bold'); td2.style.backgroundColor = '#7fb4cf';//'#7fb4cf'; td2.style.paddingLeft = '10px'; td2.setAttribute('align', 'right'); goals_button.addEventListener("click", function() { toggleGoalDiv(); }, false); export_button.addEventListener("click", function() { toggleExportDiv(); }, false); force_refresh_button.addEventListener("click", function() { console.log("Refresh button clicked."); refresh_func(); }, false); td2.appendChild(force_refresh_button); td2.appendChild(goals_button); td2.appendChild(export_button); extra_table.appendChild(row1); row1.appendChild(td1); td1.appendChild(whatsthis); row1.appendChild(td2); extra_table.appendChild(row2); row2.appendChild(content_td); footer.parentNode.insertBefore(extra_table, footer); var my_bar = document.createElement('div'); my_bar.setAttribute('id', 'my_bar'); content_td.appendChild(my_bar); my_bar.style.textAlign = "float"; var contentTable = document.createElement('table'); contentTable.setAttribute('id', 'goals_content_table'); contentTable.setAttribute('width','100%'); if (!GM_getValue('GOALS_goal_table')){ var contentRow1 = document.createElement('tr'); var noContent = document.createElement('td'); noContent.textContent = 'Uh-oh, it looks like you haven\'t set any goals. Click the \'goals\' button above to define some!'; contentTable.appendChild(contentRow1); contentRow1.appendChild(noContent); my_bar.appendChild(contentTable); } else { var goalString = GM_getValue('GOALS_goal_table'); var goalJson = JSON.parse(goalString); ////console.log("JSON parsed successfully "+goalJson); var headerRow = document.createElement('tr'); var goalTypeCell = document.createElement('td'); var goalNameCell = document.createElement('td'); var goalAmountCell = document.createElement('td'); var timeLeftCell = document.createElement('td'); var progressBarCell = document.createElement('td'); goalTypeCell.textContent = "Type"; goalNameCell.textContent = "Goal"; goalAmountCell.textContent = "Amount"; timeLeftCell.textContent = "Days Remaining"; progressBarCell.textContent = "Percent complete"; headerRow.style.backgroundColor = '#7fb4cf';//'#7fb4cf'; contentTable.appendChild(headerRow); headerRow.appendChild(goalNameCell); headerRow.appendChild(goalTypeCell); headerRow.appendChild(goalAmountCell); headerRow.appendChild(timeLeftCell); headerRow.appendChild(progressBarCell); var buttonNames = []; var goalBalanceRemaining = 0; for (var key in goalJson){ var new_row = document.createElement('tr'); var goal_type = document.createElement('td'); var goal_name = document.createElement('td'); var goal_amount = document.createElement('td'); var time_remaining = document.createElement('td'); var progCell = document.createElement('td'); var progBar = document.createElement('div'); var progLabel = document.createElement('div'); var amountInt = parseFloat(goalJson[key]['amount']); var amountStart = parseFloat(goalJson[key]['start']); var nameLink = document.createElement('button'); var pendingSum = GM_getValue('GOALS_today_pending'); var rowKey = "row_"+key; new_row.setAttribute('id', rowKey); goal_type.textContent = (goalJson[key]['type'] == 'normal' || !goalJson[key]['type'] ? (goalJson[key]['date'] ? "Deadline" : "No Deadline") : "Daily Goal"); if (goalJson[key]['type'] == 'day'){ updateDate(key); } nameLink.textContent = goalJson[key]['name']; nameLink.style.background = 'none'; nameLink.style.border = 'none'; nameLink.style.margin = '0'; nameLink.style.padding = '0'; var id = "button_"+key; buttonNames.push(id); nameLink.setAttribute('id', id); //goal_name.textContent = goalJson[key]['name']; goal_name.appendChild(nameLink); goal_amount.textContent = amountInt.formatMoney(2); var now = new Date(); daysDiff = (goalJson[key]['date'] ? datediff("days", goalJson[key]['date'], "") * -1 : null); //daysDiff *= -1; var balanceThisGoal = approvedHits - amountStart - goalBalanceRemaining; if (balanceThisGoal < 0){ goalBalanceRemaining = balanceThisGoal * -1; var progress = 0; console.log("balance this goal: "+balanceThisGoal); var progFull = Math.round(progress*100)/100; progress = (progFull >= 100 ? "100" : progFull); progFull = (progFull > 100 ? "Complete :D" : progFull+"%"); time_remaining.textContent = "Previous goals incomplete"; } else { goalBalanceRemaining = balanceThisGoal; var progress = ((goalJson[key]['type'] == 'day' ? pendingSum : balanceThisGoal) / amountInt); progress = progress * 100; var progFull = Math.round(progress*100)/100; progress = (progFull >= 100 ? "100" : progFull); progFull = (progFull > 100 ? "Complete :D" : progFull+"%"); time_remaining.textContent = (daysDiff ? (daysDiff > 0 ? daysDiff : (progress < 100 ? "Date passed :(" : "Complete :D")) : (progress < 100 ? "No date given" : "Complete :D")); } progBar.style.color = 'white'; progBar.style.backgroundColor = '#7fb4cf'; progBar.style.position = "relative"; progBar.innerHTML = ' '; progBar.setAttribute = ('align', 'left'); progBar.style.width = progress + "%"; progLabel.textContent = progFull; progLabel.style.textAlign = 'center'; progLabel.style.color = 'white'; progLabel.style.position = "absolute"; progLabel.style.top = "5%"; progLabel.style.left = "40%"; progLabel.style.zIndex = '1'; progCell.appendChild(progBar); progCell.appendChild(progLabel); progCell.style.display = "block"; progCell.style.position = "relative"; progCell.style.backgroundColor = 'gray'; contentTable.appendChild(new_row); new_row.appendChild(goal_name); new_row.appendChild(goal_type); new_row.appendChild(goal_amount); new_row.appendChild(time_remaining); new_row.appendChild(progCell); } my_bar.appendChild(contentTable); for (var i = 0; i < buttonNames.length; i++) { (function (i) { document.getElementById(buttonNames[i]).addEventListener("click", function() {if (!document.getElementById("row_"+i+"_info")) showInfo(i);}, false); })(i); } } } else { var target = document.getElementById('goals_content_table'); var contentTable2 = target.parentNode.replaceChild(document.createElement('table'), target); for(var i = contentTable2.rows.length - 1; i > -1; i--) { contentTable2.deleteRow(i); } if (!GM_getValue('GOALS_goal_table')){ var contentRow1 = document.createElement('tr'); var noContent = document.createElement('td'); noContent.textContent = 'Uh-oh, it looks like you haven\'t set any goals. Click the \'goals\' button above to define some!'; contentTable2.appendChild(contentRow1); contentRow1.appendChild(noContent); document.getElementById('my_bar').appendChild(contentTable2); } else{ var goalString = GM_getValue('GOALS_goal_table'); var goalJson = JSON.parse(goalString); var headerRow = document.createElement('tr'); var goalTypeCell = document.createElement('td'); var goalNameCell = document.createElement('td'); var goalAmountCell = document.createElement('td'); var timeLeftCell = document.createElement('td'); var progressBarCell = document.createElement('td'); goalTypeCell.textContent = "Type"; goalNameCell.textContent = "Goal"; goalAmountCell.textContent = "Amount"; timeLeftCell.textContent = "Days Remaining"; progressBarCell.textContent = "Percent complete"; headerRow.style.backgroundColor = '#7fb4cf';//'#7fb4cf'; contentTable2.appendChild(headerRow); headerRow.appendChild(goalNameCell); headerRow.appendChild(goalTypeCell); headerRow.appendChild(goalAmountCell); headerRow.appendChild(timeLeftCell); headerRow.appendChild(progressBarCell); var buttonNames = []; var goalBalanceRemaining = 0; for (var key in goalJson){ var new_row = document.createElement('tr'); var goal_type = document.createElement('td'); var goal_name = document.createElement('td'); var goal_amount = document.createElement('td'); var time_remaining = document.createElement('td'); var progCell = document.createElement('td'); var progBar = document.createElement('div'); var progLabel = document.createElement('div'); var amountInt = parseFloat(goalJson[key]['amount']); var amountStart = parseFloat(goalJson[key]['start']); var nameLink = document.createElement('button'); var pendingSum = GM_getValue('GOALS_today_pending'); var rowKey = "row_"+key; new_row.setAttribute('id', rowKey); goal_type.textContent = (goalJson[key]['type'] == 'normal' || !goalJson[key]['type'] ? (goalJson[key]['date'] ? "Deadline" : "No Deadline") : "Daily Goal"); if (goalJson[key]['type'] == 'day'){ updateDate(key); } nameLink.textContent = goalJson[key]['name']; nameLink.style.background = 'none'; nameLink.style.border = 'none'; nameLink.style.margin = '0'; nameLink.style.padding = '0'; var id = "button_"+key; buttonNames.push(id); nameLink.setAttribute('id', id); //goal_name.textContent = goalJson[key]['name']; goal_name.appendChild(nameLink); goal_amount.textContent = amountInt.formatMoney(2); var now = new Date(); daysDiff = (goalJson[key]['date'] ? datediff("days", goalJson[key]['date'], "") * -1 : null); //daysDiff *= -1; var balanceThisGoal = approvedHits - amountStart - goalBalanceRemaining; console.log("Info: "+balanceThisGoal + " " + amountInt + " " + approvedHits + " " + (approvedHits - amountStart)); if (balanceThisGoal < 0){ goalBalanceRemaining = balanceThisGoal * -1; var progress = 0; console.log("balance this goal: "+balanceThisGoal); var progFull = Math.round(progress*100)/100; progress = (progFull >= 100 ? "100" : progFull); progFull = (progFull > 100 ? "Complete :D" : progFull+"%"); time_remaining.textContent = "Previous goals incomplete"; } else { goalBalanceRemaining = balanceThisGoal; console.log("balance this goal: "+balanceThisGoal); var progress = ((goalJson[key]['type'] == 'day' ? pendingSum : balanceThisGoal) / amountInt); progress = progress * 100; var progFull = Math.round(progress*100)/100; progress = (progFull >= 100 ? "100" : progFull); progFull = (progFull > 100 ? "Complete :D" : progFull+"%"); time_remaining.textContent = (daysDiff ? (daysDiff > 0 ? daysDiff : (progress < 100 ? "Date passed :(" : "Complete :D")) : (progress < 100 ? "No date given" : "Complete :D")); } progBar.style.color = 'white'; progBar.style.backgroundColor = '#7fb4cf'; progBar.style.position = "relative"; progBar.innerHTML = ' '; progBar.setAttribute = ('align', 'left'); progBar.style.width = progress + "%"; progLabel.textContent = progFull; progLabel.style.textAlign = 'center'; progLabel.style.color = 'white'; progLabel.style.position = "absolute"; progLabel.style.top = "5%"; progLabel.style.left = "40%"; progLabel.style.zIndex = '1'; progCell.appendChild(progBar); progCell.appendChild(progLabel); progCell.style.display = "block"; progCell.style.position = "relative"; progCell.style.backgroundColor = 'gray'; contentTable2.appendChild(new_row); new_row.appendChild(goal_name); new_row.appendChild(goal_type); new_row.appendChild(goal_amount); new_row.appendChild(time_remaining); new_row.appendChild(progCell); } document.getElementById('my_bar').appendChild(contentTable2); for (var i = 0; i < buttonNames.length; i++) { (function (i) { document.getElementById(buttonNames[i]).addEventListener("click", function() {if (!document.getElementById("row_"+i+"_info")) showInfo(i);}, false); })(i); } } } } // =================================================================== // Author: Denis Howlett <[email protected]> // WWW: http://www.isocra.com/ // // NOTICE: You may use this code for any purpose, commercial or // private, without any further permission from the author. You may // remove this notice from your final code if you wish, however we // would appreciate it if at least the web site address is kept. // // You may *NOT* re-distribute this code in any way except through its // use. That means, you can include it in your product, or your web // site, or any other form where the code is actually being used. You // may not put the plain javascript up on your site for download or // include it in your javascript libraries for download. // If you wish to share this code with others, please just point them // to the URL instead. // // Please DO NOT link directly to this .js files from your site. Copy // the files to your server and use them there. Thank you. // =================================================================== /** Keep hold of the current table being dragged */ var currenttable = null; /** Capture the onmousemove so that we can see if a row from the current * table if any is being dragged. * @param ev the event (for Firefox and Safari, otherwise we use window.event for IE) */ document.onmousemove = function(ev){ if (currenttable && currenttable.dragObject) { ev = ev || window.event; var mousePos = currenttable.mouseCoords(ev); var y = mousePos.y - currenttable.mouseOffset.y; if (y != currenttable.oldY) { // work out if we're going up or down... var movingDown = y > currenttable.oldY; // update the old value currenttable.oldY = y; // update the style to show we're dragging currenttable.dragObject.style.backgroundColor = "#eee"; // If we're over a row then move the dragged row to there so that the user sees the // effect dynamically var currentRow = currenttable.findDropTargetRow(y); if (currentRow) { if (movingDown && currenttable.dragObject != currentRow) { currenttable.dragObject.parentNode.insertBefore(currenttable.dragObject, currentRow.nextSibling); } else if (! movingDown && currenttable.dragObject != currentRow) { currenttable.dragObject.parentNode.insertBefore(currenttable.dragObject, currentRow); } } } return false; } } // Similarly for the mouseup document.onmouseup = function(ev){ if (currenttable && currenttable.dragObject) { var droppedRow = currenttable.dragObject; // If we have a dragObject, then we need to release it, // The row will already have been moved to the right place so we just reset stuff droppedRow.style.backgroundColor = 'transparent'; currenttable.dragObject = null; // And then call the onDrop method in case anyone wants to do any post processing currenttable.onDrop(currenttable.table, droppedRow); currenttable = null; // let go of the table too } } /** get the source element from an event in a way that works for IE and Firefox and Safari * @param evt the source event for Firefox (but not IE--IE uses window.event) */ function getEventSource(evt) { if (window.event) { evt = window.event; // For IE return evt.srcElement; } else { return evt.target; // For Firefox } } /** * Encapsulate table Drag and Drop in a class. We'll have this as a Singleton * so we don't get scoping problems. */ function TableDnD() { /** Keep hold of the current drag object if any */ this.dragObject = null; /** The current mouse offset */ this.mouseOffset = null; /** The current table */ this.table = null; /** Remember the old value of Y so that we don't do too much processing */ this.oldY = 0; /** Initialise the drag and drop by capturing mouse move events */ this.init = function(table) { this.table = table; var rows = table.rows; //getElementsByTagName("tr") for (var i=0; i<rows.length; i++) { // John Tarr: added to ignore rows that I've added the NoDnD attribute to (Category and Header rows) var nodrag = rows[i].getAttribute("NoDrag"); if (nodrag == null || nodrag == "undefined") { //There is no NoDnD attribute on rows I want to drag this.makeDraggable(rows[i]); } } } /** This function is called when you drop a row, so redefine it in your code to do whatever you want, for example use Ajax to update the server */ this.onDrop = function(table, droppedRow) { var rows = this.table.rows; var debugStr = "rows now: "; for (var i=0; i<rows.length; i++) { debugStr += rows[i].id+" "; } console.log('row['+droppedRow.id+'] dropped<br>'+debugStr); } /** Get the position of an element by going up the DOM tree and adding up all the offsets */ this.getPosition = function(e){ var left = 0; var top = 0; /** Safari fix -- thanks to Luis Chato for this! */ if (e.offsetHeight == 0) { /** Safari 2 doesn't correctly grab the offsetTop of a table row this is detailed here: http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/ the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild. note that firefox will return a text node as a first child, so designing a more thorough solution may need to take that into account, for now this seems to work in firefox, safari, ie */ e = e.firstChild; // a table cell } while (e.offsetParent){ left += e.offsetLeft; top += e.offsetTop; e = e.offsetParent; } left += e.offsetLeft; top += e.offsetTop; return {x:left, y:top}; } /** Get the mouse coordinates from the event (allowing for browser differences) */ this.mouseCoords = function(ev){ if(ev.pageX || ev.pageY){ return {x:ev.pageX, y:ev.pageY}; } return { x:ev.clientX + document.body.scrollLeft - document.body.clientLeft, y:ev.clientY + document.body.scrollTop - document.body.clientTop }; } /** Given a target element and a mouse event, get the mouse offset from that element. To do this we need the element's position and the mouse position */ this.getMouseOffset = function(target, ev){ ev = ev || window.event; var docPos = this.getPosition(target); var mousePos = this.mouseCoords(ev); return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y}; } /** Take an item and add an onmousedown method so that we can make it draggable */ this.makeDraggable = function(item) { if(!item) return; var self = this; // Keep the context of the TableDnd inside the function item.onmousedown = function(ev) { // Need to check to see if we are an input or not, if we are an input, then // return true to allow normal processing var target = getEventSource(ev); if (target.tagName == 'INPUT' || target.tagName == 'SELECT') return true; currenttable = self; self.dragObject = this; self.mouseOffset = self.getMouseOffset(this, ev); return false; } item.style.cursor = "move"; } /** We're only worried about the y position really, because we can only move rows up and down */ this.findDropTargetRow = function(y) { var rows = this.table.rows; for (var i=0; i<rows.length; i++) { var row = rows[i]; // John Tarr added to ignore rows that I've added the NoDnD attribute to (Header rows) var nodrop = row.getAttribute("NoDrop"); if (nodrop == null || nodrop == "undefined") { //There is no NoDnD attribute on rows I want to drag var rowY = this.getPosition(row).y; var rowHeight = parseInt(row.offsetHeight)/2; if (row.offsetHeight == 0) { rowY = this.getPosition(row.firstChild).y; rowHeight = parseInt(row.firstChild.offsetHeight)/2; } // Because we always have to insert before, we need to offset the height a bit if ((y > rowY - rowHeight) && (y < (rowY + rowHeight))) { // that's the row we're over return row; } } } return null; } }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址