Created
March 25, 2013 22:23
-
-
Save mirontoli/5241360 to your computer and use it in GitHub Desktop.
A todo webpart markup for SharePoint 2010 which uses the REST API (listdata.svc) to create, update, list and delete todos from the list Tasks. It only works in Norwegian language, because it is on of the limitations of the REST API in SharePoint 2010. This code was written for a while and uses the deprecated jQuery tmpl for rendering the todos.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<style type="text/css"> | |
/*************************************************** | |
Marvelous Formula (MF) WPTodo | |
******************************************************/ | |
#todo-wp { | |
max-height: 400px; | |
/* todo overflow: auto or pagination */ | |
overflow-y: auto; | |
} | |
#todo-wp .header { | |
border-bottom: 1px solid #D0D0D0; | |
padding-bottom: 5px; | |
margin-bottom: 10px; | |
} | |
ul#todo-container { | |
list-style-type: none; | |
padding: 0px; | |
margin: 0px; | |
} | |
ul#todo-container li{ | |
margin-bottom: 5px; | |
} | |
ul#todo-container li.completed span { | |
text-decoration: line-through; | |
} | |
#add-todo { | |
background: transparent url("/_layouts/images/wptodo/add.png") no-repeat center left; | |
padding-left: 20px; | |
padding-top: 5px; | |
padding-bottom: 5px; | |
float: right; | |
} | |
#todo-form { | |
margin-top: 20px; | |
} | |
#todo-form input{ | |
margin-top: 10px; | |
} | |
</style> | |
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> | |
<script src="https://raw.github.com/jquery/jquery-tmpl/master/jquery.tmpl.min.js"></script> | |
<script id="todo-template" type="text/html"> | |
<li class="{{if StatusValue == MF.L10n.Task.completed}}completed{{/if}}"> | |
<input type="checkbox" {{if StatusValue == MF.L10n.Task.completed}}checked{{/if}}/> | |
<span>{{= this.data[MF.L10n.Task.title]}}</span> | |
</li> | |
</script> | |
<div id="todo-wp"> | |
<div class="header"> | |
<div id="add-todo" class="pointer">Legg til</div> | |
<div class="main-info"> | |
Å gjøre</div> | |
</div> | |
<div id="todo-message"></div> | |
<ul id="todo-container"> | |
</ul> | |
<div id="todo-form" class="center modalform-data s4-die"> | |
<input type="text" class="todo-text" /><br /> | |
<input type="button" | |
value="save" class="save" | |
onclick="return SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, {title: jQuery(this).siblings('.todo-text').val()});" /> | |
<input type="button" value="cancel" | |
onclick="SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, {});" /> | |
</div> | |
</div> | |
<script type="text/javascript"> | |
var MF = {}; | |
/*************************************************** | |
Marvelous Formula (MF) json and rest | |
******************************************************/ | |
MF.Utils = { | |
//changes request header for updating through REST | |
//http://msdn.microsoft.com/en-us/library/ff798339.aspx | |
beforeSendFunction: function (xhr) { | |
xhr.setRequestHeader("If-Match", "*"); | |
// Using MERGE so that the entire entity doesn't need to be sent over the wire. | |
xhr.setRequestHeader("X-HTTP-Method", 'MERGE'); | |
} | |
}; | |
MF.L10n = { | |
Task: { | |
noTasksMessage: "Det finnes ingen oppgaver akkurat nå", | |
addTask: "Legg til opgave", | |
errorMsgWithRetry: "Oops, it didn't work as expected... Trying after {0} sec..", | |
// don't translate following properties of Task, | |
// just copy values prefixed with Tasks_ from $Resoures:core.resx | |
// this is used to retrieve and update todos with listdata.svc web service | |
listName: "Oppgaver", //$Resoures:core, taskList | |
completed: "Fullført", //$Resoures:core, Tasks_Completed | |
inProgress: "Pågår", //$Resoures:core, Tasks_InProgress | |
modified: "Endret", //$Resoures:core, Modified | |
created: "Opprettet", //$Resoures:core, Created | |
title: "Tittel", //$Resoures:core, Title | |
assignedToId: "TilordnetTilId" //? "assignedToId" in lang=en (1033) | |
} | |
}; | |
MF.Todo = { | |
userId: _spPageContextInfo.userId, | |
taskUrl: undefined, | |
tryCounter: 0, | |
$msg: undefined, | |
$todoTmpl: undefined, | |
$todoContainer: undefined, | |
error: function (xhr) { | |
// see if it is culture crock after restart of the server | |
if (xhr.responseText.match(/No property .* exists/i)) { | |
MF.Todo.retrieveTodos(); | |
return; | |
} | |
MF.Todo.tryCounter++; | |
if (MF.Todo.tryCounter < 4) { | |
var errorMsg = String.format(MF.L10n.Task.errorMsgWithRetry, MF.Todo.tryCounter * 10); | |
MF.Todo.showTodoMessage(errorMsg); | |
setTimeout(MF.Todo.retrieveTodos, 10000 * MF.Todo.tryCounter); | |
} | |
errorCallback(xhr, jQuery("#todo-container").get(0)); | |
}, | |
retrieveTodos: function () { | |
MF.Todo.showTodoMessage(""); | |
MF.Todo.ensureTmplAndContainer(); | |
MF.Todo.$todoContainer.showLoadingImage(); | |
MF.Todo.getMyNotCompletedTasks(); | |
}, | |
getMyNotCompletedTasks: function () { | |
MF.Todo.taskUrl = MF.Todo.taskUrl || MF.Constants.listDataServiceUrl + MF.L10n.Task.listName; | |
var oneWeekAgo = new Date(); | |
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7); | |
var isoDateOneWeekAgo = oneWeekAgo.toISOString(); | |
var filter = String.format("{0} eq {1} and (StatusValue ne '{2}' or {3} ge datetime'{4}')", | |
MF.L10n.Task.assignedToId, | |
MF.Todo.userId, | |
MF.L10n.Task.completed, | |
MF.L10n.Task.modified, | |
isoDateOneWeekAgo); | |
var orderby = String.format("StatusValue desc, {0} desc", MF.L10n.Task.created); | |
$.ajax({ | |
type: 'GET', | |
url: MF.Todo.taskUrl, | |
contentType: 'application/json; charset=utf-8', | |
async: true, | |
dataType: "json", | |
cache: false, | |
data: { $filter: filter, $orderby: orderby }, | |
success: MF.Todo.renderTasks, | |
error: MF.Todo.error | |
}); | |
}, | |
renderTasks: function (data) { | |
MF.Todo.$todoContainer.empty(); | |
MF.Todo.$todoContainer.removeLoadingImage(); | |
var tasks = data.d.results; | |
if (tasks.length > 0) { | |
MF.Todo.appendTasks(data.d.results); | |
} | |
else { | |
MF.Todo.showTodoMessage(MF.L10n.Task.noTasksMessage); | |
} | |
MF.Todo.addClickListenerToAddButton(); | |
MF.Todo.addShortcuts(); | |
}, | |
todoModalCallback: function (result, value) { | |
if (result == SP.UI.DialogResult.OK) { | |
MF.Todo.createNewTask(value); | |
} | |
}, | |
createNewTask: function (value) { | |
if (value.title !== undefined) { | |
var task = {}; | |
task[MF.L10n.Task.title] = value.title; | |
task[MF.L10n.Task.assignedToId] = MF.Todo.userId; | |
task.StatusValue = MF.L10n.Task.inProgress; | |
var body = MF.Utils.serialize(task); | |
jQuery.ajax({ | |
type: "POST", | |
contentType: "application/json; charset=utf-8", | |
processData: false, | |
url: MF.Todo.taskUrl, | |
data: body, | |
dataType: "json", | |
converters: { "text json": MF.Utils.deserialize }, | |
success: function (data) { | |
MF.Todo.prependTasks([data.d]); | |
}, | |
error: MF.Todo.error | |
}); | |
} | |
}, | |
changeStatus: function () { | |
var $input = jQuery(this); | |
var $li = $input.parents("li"); | |
var checked = $input.is(":checked"); | |
var todo = $input.tmplItem().data; | |
var id = todo.ID; | |
var mods = {}; | |
mods.StatusValue = checked ? MF.L10n.Task.completed : MF.L10n.Task.inProgress; | |
var body = MF.Utils.serialize(mods); | |
$.ajax({ | |
type: "POST", | |
contentType: "application/json; charset=utf-8", | |
processData: false, | |
beforeSend: MF.Utils.beforeSendFunction, | |
url: MF.Todo.taskUrl + "(" + id + ")", | |
data: body, | |
dataType: "json", | |
success: function () { | |
$li.toggleClass("completed"); | |
}, | |
error: MF.Todo.error | |
}); | |
}, | |
showTodoMessage: function (msg) { | |
MF.Todo.$msg = MF.Todo.$msg || jQuery("#todo-message"); | |
MF.Todo.$msg.empty(); | |
MF.Todo.$msg.text(msg); | |
}, | |
appendTasks: function (tasks) { | |
MF.Todo.ensureTmplAndContainer(); | |
jQuery.tmpl(MF.Todo.$todoTmpl, tasks).appendTo(MF.Todo.$todoContainer).children("input").change(MF.Todo.changeStatus); | |
}, | |
prependTasks: function (tasks) { | |
MF.Todo.ensureTmplAndContainer(); | |
MF.Todo.showTodoMessage(""); | |
jQuery.tmpl(MF.Todo.$todoTmpl, tasks).prependTo(MF.Todo.$todoContainer).children("input").change(MF.Todo.changeStatus); | |
}, | |
addClickListenerToAddButton: function () { | |
jQuery("#add-todo").live({ | |
click: function () { | |
var $form = jQuery("#todo-form").clone(true); | |
$form.children(".todo-text").keydown(function (e) { | |
if (e.which == 13) { | |
jQuery(this).siblings(".save").click(); | |
} | |
}); | |
setTimeout(function () { jQuery(".ms-dlgFrameContainer .todo-text").focus(); }, 500); | |
var t = $form.toggleClass("s4-die").get(0); | |
var options = { | |
html: t, | |
title: MF.L10n.Task.addTask, | |
dialogReturnValueCallback: MF.Todo.todoModalCallback, | |
height: 150 | |
}; | |
SP.UI.ModalDialog.showModalDialog(options); | |
} | |
}); | |
}, | |
addShortcuts: function () { | |
//add keyboard shortcut | |
jQuery(document).keyup(function (e) { | |
if (e.which == 18) MF.UI.isAlt = false; | |
}); | |
jQuery(document).keydown(function (e) { | |
if (e.which == 18) MF.UI.isAlt = true; | |
// Alt-L | |
if (e.which == 76 && MF.UI.isAlt == true) { | |
jQuery("#add-todo").click(); | |
return false; | |
} | |
if (e.which == 27) { //ESC | |
SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, {}); | |
} | |
}); | |
}, | |
ensureTmplAndContainer: function () { | |
MF.Todo.$todoTmpl = MF.Todo.$todoTmpl || jQuery("#todo-template").template(); | |
MF.Todo.$todoContainer = MF.Todo.$todoContainer || jQuery("#todo-container"); | |
} | |
}; | |
jQuery(document).ready(function () { | |
MF.Todo.retrieveTodos(); | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment