// Copyright (C) 2009 BRAT Tech LLC nglr.WidgetFactory = function(serverUrl) { this.nextUploadId = 0; this.serverUrl = serverUrl; this.createSWF = swfobject.createSWF; this.onChangeListener = function(){}; }; nglr.WidgetFactory.prototype.createController = function(input, scope) { var controller; var type = input.attr('type').toLowerCase(); var exp = input.attr('name'); if (exp) exp = exp.split(':').pop(); var event = "change"; var bubbleEvent = true; if (type == 'button' || type == 'submit' || type == 'reset') { controller = new nglr.ButtonController(input[0], exp); event = "click"; bubbleEvent = false; } else if (type == 'text' || type == 'textarea') { controller = new nglr.TextController(input[0], exp); event = "keyup change"; } else if (type == 'checkbox') { controller = new nglr.CheckboxController(input[0], exp); event = "click"; } else if (type == 'radio') { controller = new nglr.RadioController(input[0], exp); event="click"; } else if (type == 'select-one') { controller = new nglr.SelectController(input[0], exp); } else if (type == 'select-multiple') { controller = new nglr.MultiSelectController(input[0], exp); } else if (type == 'file') { controller = this.createFileController(input, exp); } else { throw 'Unknown type: ' + type; } input.data('controller', controller); var binder = scope.get('$binder'); var action = function() { if (controller.updateModel(scope)) { var action = jQuery(controller.view).attr('ng-action') || ""; if (scope.evalWidget(controller, action)) { binder.updateView(scope); } } return bubbleEvent; }; jQuery(controller.view, ":input"). bind(event, action); return controller; }; nglr.WidgetFactory.prototype.createFileController = function(fileInput) { var uploadId = '__uploadWidget_' + (this.nextUploadId++); var view = nglr.FileController.template(uploadId); fileInput.after(view); var att = { data:this.serverUrl + "/admin/ServerAPI.swf", width:"95", height:"20", align:"top", wmode:"transparent"}; var par = { flashvars:"uploadWidgetId=" + uploadId, allowScriptAccess:"always"}; var swfNode = this.createSWF(att, par, uploadId); fileInput.remove(); var cntl = new nglr.FileController(view, fileInput[0].name, swfNode, this.serverUrl); jQuery(swfNode).data('controller', cntl); return cntl; }; nglr.WidgetFactory.prototype.createTextWidget = function(textInput) { var controller = new nglr.TextController(textInput); controller.onChange(this.onChangeListener); return controller; }; ///////////////////// // FileController /////////////////////// nglr.FileController = function(view, scopeName, uploader, serverUrl) { this.view = view; this.uploader = uploader; this.scopeName = scopeName; this.uploadUrl = serverUrl + '/upload'; this.attachmentBase = serverUrl + '/attachments'; this.value = null; this.lastValue = undefined; }; nglr.FileController.dispatchEvent = function(id, event, args) { var object = document.getElementById(id); var controller = jQuery(object).data("controller"); nglr.FileController.prototype['_on_' + event].apply(controller, args); }; nglr.FileController.template = function(id) { return jQuery('' + '' + '' + '' + '' + ''); }; nglr.FileController.prototype._on_cancel = function() { }; nglr.FileController.prototype._on_complete = function() { }; nglr.FileController.prototype._on_httpStatus = function(status) { nglr.alert("httpStatus:" + this.scopeName + " status:" + status); }; nglr.FileController.prototype._on_ioError = function() { nglr.alert("ioError:" + this.scopeName); }; nglr.FileController.prototype._on_open = function() { nglr.alert("open:" + this.scopeName); }; nglr.FileController.prototype._on_progress = function(bytesLoaded, bytesTotal) { }; nglr.FileController.prototype._on_securityError = function() { nglr.alert("securityError:" + this.scopeName); }; nglr.FileController.prototype._on_uploadCompleteData = function(data) { this.value = nglr.fromJson(data); this.value.url = this.attachmentBase + '/' + this.value.id + '/' + this.value.text; this.view.find("input").attr('checked', true); var scope = this.view.scope(); this.updateModel(scope); scope.get('$binder').updateView(); }; nglr.FileController.prototype._on_select = function(name, size, type) { this.name = name; this.view.find("a").text(name).attr('href', name); this.view.find("span").text(filters.bytes(size)); this.upload(); }; nglr.FileController.prototype.updateModel = function(scope) { var isChecked = this.view.find("input").attr('checked'); var value = isChecked ? this.value : null; if (this.lastValue === value) { return false; } else { scope.set(this.scopeName, value); return true; } }; nglr.FileController.prototype.updateView = function(scope) { var modelValue = scope.get(this.scopeName); if (modelValue && this.value !== modelValue) { this.value = modelValue; this.view.find("a"). attr("href", this.value.url). text(this.value.name); this.view.find("span").text(filters.bytes(this.value.size)); } this.view.find("input").attr('checked', !!modelValue); }; nglr.FileController.prototype.upload = function() { if (this.name) { this.uploader.uploadFile(this.uploadUrl); } }; /////////////////////// // NullController /////////////////////// nglr.NullController = function(view) {this.view = view;}; nglr.NullController.prototype.updateModel = function() { return true; }; nglr.NullController.prototype.updateView = function() { }; nglr.NullController.instance = new nglr.NullController(); /////////////////////// // ButtonController /////////////////////// nglr.ButtonController = function(view) {this.view = view;}; nglr.ButtonController.prototype.updateModel = function(scope) { return true; }; nglr.ButtonController.prototype.updateView = function(scope) {}; /////////////////////// // TextController /////////////////////// nglr.TextController = function(view, exp) { this.view = view; this.exp = exp; this.validator = view.getAttribute('ng-validate'); this.required = typeof view.attributes['ng-required'] != "undefined"; this.lastErrorText = null; this.lastValue = undefined; this.initialValue = view.value; var widget = view.getAttribute('ng-widget'); if (widget === 'datepicker') { jQuery(view).datepicker(); } }; nglr.TextController.prototype.updateModel = function(scope) { var value = this.view.value; if (this.lastValue === value) { return false; } else { scope.set(this.exp, value); this.lastValue = value; return true; } }; nglr.TextController.prototype.updateView = function(scope) { var view = this.view; var value = scope.get(this.exp); if (typeof value === "undefined") { value = this.initialValue; scope.set(this.exp, value); } value = value ? value : ''; if (this.lastValue != value) { view.value = value; this.lastValue = value; } var isValidationError = false; view.removeAttribute('ng-error'); if (this.required) { isValidationError = !(value && value.length > 0); } var errorText = isValidationError ? "Required Value" : null; if (!isValidationError && this.validator && value) { errorText = scope.validate(this.validator, value); isValidationError = !!errorText; } if (this.lastErrorText !== errorText) { this.lastErrorText = isValidationError; if (errorText !== null) { view.setAttribute('ng-error', errorText); scope.markInvalid(this); } jQuery(view).toggleClass('ng-validation-error', isValidationError); } }; /////////////////////// // CheckboxController /////////////////////// nglr.CheckboxController = function(view, exp) { this.view = view; this.exp = exp; this.lastValue = undefined; this.initialValue = view.checked ? view.value : ""; }; nglr.CheckboxController.prototype.updateModel = function(scope) { var input = this.view; var value = input.checked ? input.value : ''; if (this.lastValue === value) { return false; } else { scope.setEval(this.exp, value); this.lastValue = value; return true; } }; nglr.CheckboxController.prototype.updateView = function(scope) { var input = this.view; var value = scope.eval(this.exp); if (typeof value === "undefined") { value = this.initialValue; scope.setEval(this.exp, value); } input.checked = input.value == (''+value); }; /////////////////////// // SelectController /////////////////////// nglr.SelectController = function(view, exp) { this.view = view; this.exp = exp; this.lastValue = undefined; this.initialValue = view.value; }; nglr.SelectController.prototype.updateModel = function(scope) { var input = this.view; if (input.selectedIndex < 0) { scope.set(this.exp, null); } else { var value = this.view.value; if (this.lastValue === value) { return false; } else { scope.set(this.exp, value); this.lastValue = value; return true; } } }; nglr.SelectController.prototype.updateView = function(scope) { var input = this.view; var value = scope.get(this.exp); if (typeof value === 'undefined') { value = this.initialValue; scope.set(this.exp, value); } if (value !== this.lastValue) { input.value = value ? value : ""; this.lastValue = value; } }; /////////////////////// // MultiSelectController /////////////////////// nglr.MultiSelectController = function(view, exp) { this.view = view; this.exp = exp; this.lastValue = undefined; this.initialValue = this.selected(); }; nglr.MultiSelectController.prototype.selected = function () { var value = []; var options = this.view.options; for ( var i = 0; i < options.length; i++) { var option = options[i]; if (option.selected) { value.push(option.value); } } return value; }; nglr.MultiSelectController.prototype.updateModel = function(scope) { var value = this.selected(); // TODO: This is wrong! no caching going on here as we are always comparing arrays if (this.lastValue === value) { return false; } else { scope.set(this.exp, value); this.lastValue = value; return true; } }; nglr.MultiSelectController.prototype.updateView = function(scope) { var input = this.view; var selected = scope.get(this.exp); if (typeof selected === "undefined") { selected = this.initialValue; scope.set(this.exp, selected); } if (selected !== this.lastValue) { var options = input.options; for ( var i = 0; i < options.length; i++) { var option = options[i]; option.selected = selected.contains(option.value); } this.lastValue = selected; } }; /////////////////////// // RadioController /////////////////////// nglr.RadioController = function(view, exp) { this.view = view; this.exp = exp; this.lastChecked = undefined; this.lastValue = undefined; this.inputValue = view.value; this.initialValue = view.checked ? view.value : null; }; nglr.RadioController.prototype.updateModel = function(scope) { var input = this.view; if (this.lastChecked) { return false; } else { input.checked = true; this.lastValue = scope.set(this.exp, this.inputValue); this.lastChecked = true; return true; } }; nglr.RadioController.prototype.updateView = function(scope) { var input = this.view; var value = scope.get(this.exp); if (this.initialValue && typeof value === "undefined") { value = this.initialValue; scope.set(this.exp, value); } if (this.lastValue != value) { this.lastChecked = input.checked = this.inputValue == (''+value); this.lastValue = value; } }; /////////////////////// //ElementController /////////////////////// nglr.BindUpdater = function(view, exp) { this.view = view; this.exp = exp.parseBindings(); this.hasError = false; this.scopeSelf = {element:view}; }; nglr.BindUpdater.toText = function(obj) { var e = nglr.escapeHtml; switch(typeof obj) { case "string": case "boolean": case "number": return e(obj); case "function": return nglr.BindUpdater.toText(obj()); case "object": if (nglr.isNode(obj)) { return nglr.outerHTML(obj); } else if (obj && obj.TAG === filters.Meta.TAG) { switch(typeof obj.html) { case "string": case "number": return obj.html; case "function": return obj.html(); default: break; } switch(typeof obj.text) { case "string": case "number": return e(obj.text); case "function": return e(obj.text()); default: break; } } if (obj === null) return ""; return e(nglr.toJson(obj, true)); default: return ""; } }; nglr.BindUpdater.prototype.updateModel = function(scope) {}; nglr.BindUpdater.prototype.updateView = function(scope) { var html = []; var parts = this.exp; var length = parts.length; for(var i=0; i iteratorLength; --r) { var unneeded = this.children.pop(); unneeded.element.removeNode(); } // Special case for option in select if (child && child.element[0].nodeName === "OPTION") { var select = jQuery(child.element[0].parentNode); var cntl = select.data('controller'); if (cntl) { cntl.lastValue = undefined; cntl.updateView(scope); } } }); }; ////////////////////////////////// // PopUp ////////////////////////////////// nglr.PopUp = function(doc) { this.doc = doc; }; nglr.PopUp.OUT_EVENT = "mouseleave mouseout click dblclick keypress keyup"; nglr.PopUp.prototype.bind = function () { var self = this; this.doc.find('.ng-validation-error,.ng-exception'). live("mouseover", nglr.PopUp.onOver); }; nglr.PopUp.onOver = function(e) { nglr.PopUp.onOut(); var jNode = jQuery(this); jNode.bind(nglr.PopUp.OUT_EVENT, nglr.PopUp.onOut); var position = jNode.position(); var de = document.documentElement; var w = self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth; var hasArea = w - position.left; var width = 300; var title = jNode.hasClass("ng-exception") ? "EXCEPTION:" : "Validation error..."; var msg = jNode.attr("ng-error"); var x; var arrowPos = hasArea>(width+75) ? "left" : "right"; var tip = jQuery( "
" + "
" + "
"+title+"
" + "
"+msg+"
" + "
"); jQuery("body").append(tip); if(arrowPos === 'left'){ x = position.left + this.offsetWidth + 11; }else{ x = position.left - (width + 15); tip.find('.ng-arrow-right').css({left:width+1}); } tip.css({left: x+"px", top: (position.top - 3)+"px"}); return true; }; nglr.PopUp.onOut = function() { jQuery('#ng-callout'). unbind(nglr.PopUp.OUT_EVENT, nglr.PopUp.onOut). remove(); return true; }; ////////////////////////////////// // Status ////////////////////////////////// nglr.Status = function (body) { this.body = body; this.requestCount = 0; }; nglr.Status.ANGULAR = "<a class='ng-angular-logo' href='http://www.getangular.com'>&lt;angular/&gt;</a>™"; nglr.Status.prototype.beginRequest = function () { if (this.requestCount === 0) { <<<<<<< HEAD:public/javascripts/nglr/Widgets.js this.dialogView = jQuery('
Please Wait...
'); ======= this.dialogView = jQuery('
Please Wait...
'); this.progressWidget = this.dialogView.find("div"); this.progressWidget.progressbar({value:0}); >>>>>>> master:public/javascripts/nglr/Widgets.js this.dialogView.dialog({bgiframe:true, minHeight:50, modal:true}); this.maxRequestCount = 0; } this.requestCount++; this.maxRequestCount++; }; nglr.Status.prototype.endRequest = function () { this.requestCount--; if (this.requestCount === 0) { this.dialogView.dialog("destroy"); this.dialogView.remove(); this.dialogView = null; } };