/** * Smarty plugin that allows you to code a block of HTML formatted nicely for development, but convert it to JSON for use with Javascript. * * @param array The params from smarty tag. * @param string The HTML code. * @param object WFSmarty object of the current tpl. * @return string The rendered HTML. */ function smarty_block_JSON($params, $content, &$smarty, &$repeat) { // beginning or end block? if (isset($content)) { print WFJSON::encode($content); } }
public function getSetupJS() { $options = array(); foreach (array('base', 'loadOptional', 'allowRollup', 'combine', 'comboBase') as $k) { if ($this->{$k}() === NULL) { continue; } $options[$k] = $this->{$k}(); } if ($this->debug()) { $options['filter'] = "DEBUG"; $options['allowRollup'] = false; } $optionsJSON = WFJSON::encode($options); return "<script>new PHOCOA.YUI({$optionsJSON});</script>"; }
/** * Exception handler for the WFRequestController. * * This is basically the uncaught exception handler for the request cycle. * We want to have this in the request object because we want the result to be displayed within our skin system. * This function will display the appropriate error page based on the deployment mode for this machine. * * @param Exception The exception object to handle. */ function handleException(Exception $e) { // give ourselves a little more memory so we can process the exception ini_set('memory_limit', memory_get_usage() + 25000000); // grab error_get_last ASAP so that it cannot get adulterated by other things. // we will inject it into things downstream that want it. $standardErrorData = WFExceptionReporting::generatedStandardizedErrorDataFromException($e); // let the current module try to handle the exception if ($this->rootModuleInvocation) { $this->rootModuleInvocation->handleUncaughtException($e); } $webAppDelegate = WFWebApplication::sharedWebApplication()->delegate(); if (is_object($webAppDelegate) && method_exists($webAppDelegate, 'handleUncaughtException')) { $handled = $webAppDelegate->handleUncaughtException($e); if ($handled) { return; } } WFExceptionReporting::log($standardErrorData); $exceptionPage = new WFSmarty(); // LEGACY tpl var setup (in case there are old .tpl's that expect it // build stack of errors (php 5.3+) if (method_exists($e, 'getPrevious')) { $tmpE = $e; $allExceptions = array(); do { $allExceptions[] = $tmpE; } while ($tmpE = $tmpE->getPrevious()); } else { $allExceptions = array($e); } $exceptionPage->assign('exceptions', $allExceptions); $exceptionPage->assign('exceptionClass', get_class($allExceptions[0])); $exceptionPage->assign('home_url', WWW_ROOT . '/'); // end LEGACY // modern format $exceptionPage->assign('location', "http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"); $exceptionPage->assign('headline', "{$standardErrorData[0]['title']}: {$standardErrorData[0]['message']}"); $exceptionPage->assign('standardErrorData', $standardErrorData); $exceptionPage->assign('standardErrorDataJSON', WFJSON::encode(array('error' => $standardErrorData, '$_SERVER' => $_SERVER, '$_REQUEST' => $_REQUEST, '$_SESSION' => $_SESSION))); if (IS_PRODUCTION) { $exceptionPage->setTemplate(WFWebApplication::appDirPath(WFWebApplication::DIR_SMARTY) . '/app_error_user.tpl'); } else { $exceptionPage->setTemplate(WFWebApplication::appDirPath(WFWebApplication::DIR_SMARTY) . '/app_error_developer.tpl'); } // display the error $body_html = $exceptionPage->render(false); // output error info header("HTTP/1.0 500 Uncaught Exception"); if ($this->isAjax()) { print strip_tags($body_html); } else { $skin = new WFSkin(); $skin->setDelegateName(WFWebApplication::sharedWebApplication()->defaultSkinDelegate()); $skin->setBody($body_html); $skin->setTitle("An error has occurred."); $skin->render(); } }
function smarty_modifier_json($in) { return WFJSON::encode($in); }
function render($blockContent = NULL) { $loader = WFYAHOO_yuiloader::sharedYuiLoader(); // jquery $loader->addModule('jquery', 'js', NULL, 'http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.js', NULL, NULL, NULL, NULL); // jquery-ui $loader->addModule('jqueryui-css', 'css', NULL, 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css', NULL, NULL, NULL, NULL); $loader->addModule('jqueryui', 'js', NULL, 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.js', array('jquery', 'jqueryui-css'), NULL, NULL, NULL); // query-file-uploader $loader->addModule('jquery-file-uploader', 'js', NULL, $this->getWidgetWWWDir() . '/jquery.fileupload.js', array('jquery'), NULL, NULL, NULL); // and the UI $loader->addModule('jquery-file-uploader-ui-css', 'css', NULL, $this->getWidgetWWWDir() . '/jquery.fileupload-ui.css', NULL, NULL, array('jqueryui-css'), NULL); $loader->addModule('jquery-file-uploader-ui', 'js', NULL, $this->getWidgetWWWDir() . '/jquery.fileupload-ui.js', array('jquery-file-uploader', 'jqueryui', 'jquery-file-uploader-ui-css'), NULL, NULL, NULL); $loader->yuiRequire('jquery-file-uploader-ui'); // @todo In future this should not need to be a WFForm subclass; should be able to drop it in a form anywhere. //$form = $this->getForm(); //if (!$form) throw new WFException("WFHTML5_Uploader must be a child of a WFForm."); $form = $this; // craft a WFRPC that we can insert into the form stream to have our callback fire $rpc = WFRPC::RPC()->setInvocationPath($this->page->module()->invocation()->invocationPath())->setTarget('#page#' . $this->id)->setAction('_handleAsyncSingleUpload')->setForm($this)->setIsAjax(true); $uploadFormData = json_encode($rpc->rpcAsParameters($this)); // figure out vars for drop-in into HTML block $sequentialUploads = var_export($this->maxConcurrentUploads == 1, true); $autoupload = var_export($this->autoupload, true); $fileInputName = "{$this->getInputFileName()}[]"; // HTML $formInnardsHTML = <<<END {$blockContent} <input type="file" name="{$fileInputName}" multiple> <button type="submit" name="action|{$this->id}">Upload</button> <div class="file_upload_label">Click or Drop to Upload</div> END; $html = parent::render($formInnardsHTML); $maxUploadBytesJSON = WFJSON::encode($this->maxUploadBytes); // progress indicators after form since the blueimp plugin takes over the entire form area for drag-n-drop $html .= <<<END <div id="{$this->id}_progressAll" style="display: none;"></div> <table id="{$this->id}_table" style="display: none;"></table> END; $withJqueryJS = <<<END function() { jQuery.noConflict(); jQuery(function () { window.uploader = jQuery('#{$form->id()}').fileUploadUI({ formData: {$uploadFormData}, sequentialUploads: {$sequentialUploads}, beforeSend: function (event, files, index, xhr, handler, callBack) { document.fire ('WFHTML5_Uploader:uploadStart'); jQuery('#{$this->id}_table, #{$this->id}_progressAll').show(); var fileSize = files[index].fileSize ? files[index].fileSize : files[index].size // Firefox calls it file.size instead of file.fileSize if ({$maxUploadBytesJSON} && fileSize > {$maxUploadBytesJSON}) { var json = { 'name': files[index].name, 'description': ('File exceeds maximum file size of ' + {$maxUploadBytesJSON} + ' bytes.'), 'uploadOK': false }; handler.downloadRow = handler.buildDownloadRow(json, handler); handler.replaceNode(handler.uploadRow, handler.downloadRow, null); return; } if ({$autoupload}) { callBack(); } }, progressAllNode: jQuery('#{$this->id}_progressAll'), uploadTable: jQuery('#{$this->id}_table'), onCompleteAll: function() { var autoRedirectToUrlOnCompleteAll = '{$this->autoRedirectToUrlOnCompleteAll}'; if (autoRedirectToUrlOnCompleteAll) { document.fire ('WFHTML5_Uploader:uploadAllComplete'); window.location.href = autoRedirectToUrlOnCompleteAll; } }, buildUploadRow: function (files, index) { return jQuery('<tr>' + '<td width="175">' + files[index].name + '<\\/td>' + '<td width="1"> <\\/td>' + '<td width="250"> <\\/td>' + '<td width="16" class="file_upload_cancel">' + '<button class="ui-state-default ui-corner-all" title="Cancel">' + '<span class="ui-icon ui-icon-cancel">Cancel<\\/span>' + '<\\/button><\\/td>' + '<td class="file_upload_progress" style="width: 160px"><div><\\/div><\\/td>' + '<\\/tr>'); }, buildDownloadRow: function (file, handler) { var thumbHTML = ' '; if (file.thumb) { thumbHTML = '<img s'+'rc="'+file.thumb+'" style="float: right;"/>'; } return jQuery('<tr>' + '<td width="175">' + file.name + '<\\/td>' + '<td width="' + (thumbHTML ? 100 : 1) + '">' + thumbHTML + '<\\/td>' + '<td width="250">' + file.description + '<\\/td>' + '<td width="16"><span class="ui-icon ' + (file.uploadOK ? 'ui-icon-check' : 'ui-icon-alert') + '"><\\/span><\\/td>' + '<td><\\/td>' + '<\\/tr>'); } }); }); } END; $bootstrapJS = $loader->jsLoaderCode($withJqueryJS); $html .= <<<END <script> {$bootstrapJS} </script> END; return $html; }
function initJS($blockcontent) { $script = "\nPHOCOA.namespace('widgets.{$this->id}');\nPHOCOA.widgets.{$this->id}.loadData = function(node, fnLoadComplete)\n{\n var tNode = node;\n var pathParts = new Array();\n while ( true ) {\n pathParts.push(tNode.nodeId);\n tNode = tNode.parent;\n if (!tNode || tNode.nodeId == null) break;\n }\n pathParts.reverse();\n var path = pathParts.join('|');\n"; if ($this->dynamicDataLoader) { $script .= "\n var rpc = new PHOCOA.WFRPC('" . WWW_ROOT . '/' . $this->page()->module()->invocation()->invocationPath() . "', '#page#{$this->id}', 'ajaxLoadData');\n rpc.callback.success = PHOCOA.widgets.{$this->id}.loadDataHandleSuccess;\n rpc.callback.failure = PHOCOA.widgets.{$this->id}.loadDataHandleFailure;\n rpc.callback.argument = { loadComplete: fnLoadComplete, node: node };\n " . ($this->queryFieldId ? "var qVal = PHOCOA.widgets.{$this->queryFieldId}.getValue();" : NULL) . "\n rpc.execute(path" . ($this->queryFieldId ? ", qVal" : NULL) . ");\n "; } else { // backwards compatibility $script .= "\n var url = '{$this->bcCallback}/' + encodeURIComponent(path);\n var callback = {\n success: PHOCOA.widgets.{$this->id}.loadDataHandleSuccess,\n failure: PHOCOA.widgets.{$this->id}.loadDataHandleFailure,\n argument: { loadComplete: fnLoadComplete, node: node }\n };\n YAHOO.util.Connect.asyncRequest('GET', url, callback);\n "; } $script .= "\n};\n\nPHOCOA.widgets.{$this->id}.loadDataHandleSuccess = function(o)\n{\n if (o.argument.node.isRoot())\n {\n // always clear all kids on root before adding; this solves the problem of multiple reloadTree() being called before first result rolls in (and thus merges results)\n PHOCOA.runtime.getObject('{$this->id}').removeChildren(o.argument.node);\n }\n\n // process XML data - this is the only x-browser way I could find since Safari doesn't support XPath yet\n var xml = o.responseXML.documentElement;\n var items = xml.getElementsByTagName('item');\n for (var i = 0; i < items.length; i++)\n {\n var nodeData = items[i].firstChild.nodeValue;\n var nodeId = items[i].getAttribute('nodeId');\n var couldHaveChildren = items[i].getAttribute('couldHaveChildren');\n var newNode = new YAHOO.widget.{$this->nodeType}(nodeData, o.argument.node, false, true);\n newNode.nodeId = nodeId;\n if (couldHaveChildren == '0')\n {\n newNode.dynamicLoadComplete = true;\n }\n " . ($this->enableDragDropTree ? "new DDSend(newNode.contentElId);" : NULL) . "\n }\n\n if (items.length == 0 && o.argument.node.isRoot())\n {\n \$('{$this->id}_status').show().update('No matches.');\n }\n else\n {\n \$('{$this->id}_status').hide();\n }\n\n // complete node loading\n o.argument.loadComplete();\n\n if (o.argument.node.isRoot() && " . ($this->autoExpandUntilChoices ? 1 : 0) . ") PHOCOA.widgets.{$this->id}.autoExpand(o.argument.node);\n};\n\nPHOCOA.widgets.{$this->id}.loadDataHandleFailure = function(o)\n{\n \$('{$this->id}_status').hide();\n alert('failed to load data');\n};\n\n// utility functions not included in YUI Tree\nPHOCOA.widgets.{$this->id}.reloadTree = function()\n{\n var tree = PHOCOA.runtime.getObject('{$this->id}');\n var rootNode = tree.getRoot();\n tree.removeChildren(rootNode);\n rootNode.refresh();\n PHOCOA.widgets.{$this->id}.loadData(rootNode, function() { rootNode.loadComplete(); });\n};\nPHOCOA.widgets.{$this->id}.reloadNode = function(node)\n{\n var tree = PHOCOA.runtime.getObject('{$this->id}');\n tree.removeChildren(node);\n node.refresh();\n PHOCOA.widgets.{$this->id}.loadData(node, function() { node.loadComplete(); });\n};\nPHOCOA.widgets.{$this->id}.autoExpand = function(node) { if (node.children.length === 1) node.children[0].expand(); };\n// end util funcs\n\nPHOCOA.widgets.{$this->id}.init = function()\n{\n var {$this->id} = new YAHOO.widget.TreeView('{$this->id}');\n var root = {$this->id}.getRoot();\n var nodes = new Array();\n"; // load the root data set if it hasn't been set already if ($this->value === NULL) { if ($this->dynamicDataLoader) { $this->setValue(call_user_func($this->dynamicDataLoader, NULL, NULL)); } else { $this->setValue(array()); } } // add items // iterative algorithm for travesing nested list and creating JS to add all nodes in proper order // initailze itemStack with first level $itemStack = array(); foreach (array_reverse($this->value) as $child) { $itemStack[] = $child; $itemParentPaths[] = NULL; } while (true) { // get item to work with; flow control $currentItem = array_pop($itemStack); if (!$currentItem) { break; } if (!$currentItem instanceof WFYAHOO_widget_TreeViewNode) { throw new Exception("Items in tree data must be WFYAHOO_widget_TreeViewNode instances."); } $currentParentPath = array_pop($itemParentPaths); // if we're not in dynamic data loading mode, we can auto-calculate couldHaveChildren if (!$this->dynamicallyLoadsData()) { if (!$currentItem->hasChildren()) { $currentItem->setCouldHaveChildren(false); } } // add item to tree $labelPath = $currentParentPath . "|" . $currentItem->id(); if ($currentParentPath) { $parentNode = "nodes['{$currentParentPath}']"; } else { $parentNode = "root"; } $script .= " nodes['{$labelPath}'] = new YAHOO.widget.{$this->nodeType}(" . WFJSON::encode($currentItem->data()) . ", {$parentNode}, false, true);\n"; $script .= " nodes['{$labelPath}'].nodeId = '" . addslashes($currentItem->id()) . "';\n"; if (!$currentItem->couldHaveChildren()) { $script .= " nodes['{$labelPath}'].dynamicLoadComplete = true;\n"; } $script .= $this->enableDragDropTree ? "new DDSend(nodes['{$labelPath}'].contentElId);" : NULL; if ($currentItem->hasChildren()) { foreach (array_reverse($currentItem->children()) as $child) { $itemStack[] = $child; $itemParentPaths[] = $labelPath; } } } // add dynamic loader if needed if ($this->dynamicallyLoadsData()) { $script .= "{$this->id}.setDynamicLoad(PHOCOA.widgets.{$this->id}.loadData, 1);\n"; //throw( new WFException("dynamic loading not yet implemented")); } if ($this->autoExpandUntilChoices) { $script .= "{$this->id}.subscribe('expandComplete', PHOCOA.widgets.{$this->id}.autoExpand);"; } if ($this->expandOnClick === false) { $script .= "{$this->id}.subscribe('clickEvent', function(e) { return false; });"; } // finish script init function $script .= "\n PHOCOA.runtime.addObject({$this->id}, '{$this->id}');\n {$this->id}.draw();\n "; if ($this->queryFieldId) { $qf = $this->page()->outlet($this->queryFieldId); if (!$qf instanceof WFSearchField) { throw new WFException("queryFieldId must be the ID of a WFSearchField."); } $script .= "\n YAHOO.util.Event.onContentReady('{$this->queryFieldId}', function() {\n var queryField = \$('{$this->queryFieldId}');\n queryField.observe('phocoa:WFSearchField:search', PHOCOA.widgets.{$this->id}.reloadTree);\n queryField.observe('phocoa:WFSearchField:clear', PHOCOA.widgets.{$this->id}.reloadTree);\n });\n "; } $script .= "\n}\n"; return $script; }
function initJS($blockContent) { // craft a WFRPC that we can insert into the form stream to have our callback fire $rpc = WFRPC::RPC()->setInvocationPath($this->page->module()->invocation()->invocationPath())->setTarget('#page#' . $this->id)->setAction('handleUploadedFile')->setForm($this->getForm())->setRunsIfInvalid(true)->setIsAjax(true); $html = "\n PHOCOA.widgets.{$this->id}.status = { 'READY': 0, 'UPLOADING': 1, 'COMPLETE': 2};\n PHOCOA.widgets.{$this->id}.summaryStatus = PHOCOA.widgets.{$this->id}.status.READY;\n PHOCOA.widgets.{$this->id}.emptyFileListDisplay = function() {\n PHOCOA.widgets.{$this->id}.filesToUploadTracker = {};\n PHOCOA.widgets.{$this->id}.filesToUploadTotalBytes = 0;\n \$('{$this->id}_fileList').update('').hide();\n };\n PHOCOA.widgets.{$this->id}.makePrettySize = function(sz, decimals) {\n if (typeof decimals === 'undefined')\n {\n decimals = 2;\n }\n var suffixes = ['Bytes','KB','MB','GB','TB'];\n var i = 0;\n\n while (sz >= 1024 && (i < suffixes.length - 1)){\n sz /= 1024;\n i++;\n }\n return Math.round(sz*Math.pow(10,decimals))/Math.pow(10,decimals) + ' ' + suffixes[i];\n };\n PHOCOA.widgets.{$this->id}.init = function() {\n PHOCOA.widgets.{$this->id}.emptyFileListDisplay(); // initialize\n\n YAHOO.util.Event.onDOMReady(function () { \n var uiLayer = YAHOO.util.Dom.getRegion('{$this->id}_browseTrigger');\n var overlay = YAHOO.util.Dom.get('{$this->id}');\n YAHOO.util.Dom.setStyle(overlay, 'width', uiLayer.width + 'px');\n YAHOO.util.Dom.setStyle(overlay, 'height', uiLayer.height + 'px');\n });\n\n YAHOO.widget.Uploader.SWFURL = '" . WFYAHOO_yuiloader::sharedYuiLoader()->localYUI() . "uploader/assets/uploader.swf'; \n var uploader = new YAHOO.widget.Uploader('{$this->id}');\n PHOCOA.runtime.addObject(uploader, '{$this->id}');\n\n // can't customize until the SWF is ready\n uploader.addListener('contentReady', function() {\n uploader.setAllowMultipleFiles(" . ($this->allowMultiple ? 'true' : 'false') . ");\n uploader.setSimUploadLimit(1);\n });\n\n \$('{$this->id}_uploadTrigger').observe('click', function() {\n PHOCOA.runtime.getObject('{$this->id}').uploadAll('" . $rpc->url() . "', 'POST', " . WFJSON::encode($rpc->rpcAsParameters()) . ", '{$this->id}');\n });\n\n uploader.addListener('fileSelect', function(e) {\n // fileSelect sends ALL files tracked by flash, not just the ones added in the most recent file select dialog\n PHOCOA.widgets.{$this->id}.emptyFileListDisplay();\n \$('{$this->id}_fileList').show();\n\n var files = \$H(e.fileList).values();\n\n files.pluck('id').each(function(o) {\n PHOCOA.widgets.{$this->id}.filesToUploadTracker[o] = {\n id: e.fileList[o].id,\n name: e.fileList[o].name,\n size: e.fileList[o].size,\n sizeProgress: 0,\n status: PHOCOA.widgets.{$this->id}.status.READY,\n error: false,\n resultMessage: null\n };\n });\n "; if ($this->maxUploadBytes !== NULL) { $html .= "\n var tooBig = [];\n var justRight = {};\n \$H(PHOCOA.widgets.{$this->id}.filesToUploadTracker).values().each(function(o) {\n if (o.size > {$this->maxUploadBytes})\n {\n PHOCOA.runtime.getObject('{$this->id}').removeFile(o.id);\n tooBig.push(o);\n }\n else\n {\n justRight[o.id] = o;\n }\n });\n PHOCOA.widgets.{$this->id}.filesToUploadTracker = justRight;\n if (tooBig.length)\n {\n alert('The following files will be skipped because they are more than ' + PHOCOA.widgets.{$this->id}.makePrettySize({$this->maxUploadBytes}) + \":\\n- \" + tooBig.pluck('name').join(\"\\n- \"));\n }\n "; } $html .= "\n \$H(PHOCOA.widgets.{$this->id}.filesToUploadTracker).values().pluck('size').each(function(o) {\n PHOCOA.widgets.{$this->id}.filesToUploadTotalBytes += o;\n });\n PHOCOA.widgets.{$this->id}.updateProgress();\n });\n uploader.addListener('uploadStart', function(e) {\n PHOCOA.widgets.{$this->id}.summaryStatus = PHOCOA.widgets.{$this->id}.status.UPLOADING;\n PHOCOA.widgets.{$this->id}.updateProgress();\n PHOCOA.widgets.{$this->id}.filesToUploadTracker[e.id].status = PHOCOA.widgets.{$this->id}.status.UPLOADING;\n });\n uploader.addListener('uploadProgress', function(e) {\n PHOCOA.widgets.{$this->id}.filesToUploadTracker[e.id].sizeProgress = e.bytesLoaded;\n PHOCOA.widgets.{$this->id}.updateProgress();\n });\n uploader.addListener('uploadError', function(e) {\n PHOCOA.widgets.{$this->id}.filesToUploadTracker[e.id].error = true;\n PHOCOA.widgets.{$this->id}.filesToUploadTracker[e.id].resultMessage = e.status;\n PHOCOA.widgets.{$this->id}.filesToUploadTracker[e.id].status = PHOCOA.widgets.{$this->id}.status.COMPLETE;\n PHOCOA.widgets.{$this->id}.updateProgress();\n });\n uploader.addListener('uploadComplete', function(e) {\n PHOCOA.widgets.{$this->id}.filesToUploadTracker[e.id].sizeProgress = PHOCOA.widgets.{$this->id}.filesToUploadTracker[e.id].size;\n PHOCOA.widgets.{$this->id}.filesToUploadTracker[e.id].status = PHOCOA.widgets.{$this->id}.status.COMPLETE;\n PHOCOA.widgets.{$this->id}.updateProgress();\n\n // are we done with ALL uploads?\n if (\$H(PHOCOA.widgets.{$this->id}.filesToUploadTracker).values().all(function(o) { return o.sizeProgress === o.size; }))\n {\n PHOCOA.widgets.{$this->id}.summaryStatus = PHOCOA.widgets.{$this->id}.status.COMPLETE;\n \$('{$this->id}_progress').update('Upload complete.');\n PHOCOA.runtime.getObject('{$this->id}').clearFileList(); // remove files from flash\n //PHOCOA.widgets.{$this->id}.emptyFileListDisplay();\n document.fire('WFYAHOO_widget_Uploader:allUploadsComplete', { uploadId: '{$this->id}' });\n if (" . WFJSON::encode(!empty($this->continueURL)) . ")\n {\n window.location = '{$this->continueURL}';\n }\n }\n });\n };\n PHOCOA.widgets.{$this->id}.updateProgress = function() {\n // update summary progress bar\n var allFilesToUpload = \$H(PHOCOA.widgets.{$this->id}.filesToUploadTracker).values();\n\n if (allFilesToUpload.any(function(o) { return o.status !== PHOCOA.widgets.{$this->id}.status.READY; }))\n {\n var uploadProgressBytes = 0;\n allFilesToUpload.pluck('sizeProgress').each( function(o) {\n uploadProgressBytes += o;\n });\n var msg = 'Upload progress: ' + Math.round(uploadProgressBytes*100 / PHOCOA.widgets.{$this->id}.filesToUploadTotalBytes) + '%';\n \$('{$this->id}_progress').update(msg);\n }\n\n // Update per-file progress\n // Sort by amount of upload left, descending. makes it easy to spot what's left and problems.\n allFilesToUpload.sort( function(a,b) { return a.size - a.sizeProgress < b.size - b.sizeProgress } );\n \$('{$this->id}_fileList').update('<strong>' + allFilesToUpload.length + ' file(s) selected:</strong><table><tr><th>Name</th><th nowrap>Size</th><th nowrap>Status</th></tr>' + allFilesToUpload.collect(function(o) { \n var msg = '<tr>';\n msg += '<td>' + o.name + '</td>';\n msg += '<td>' + PHOCOA.widgets.{$this->id}.makePrettySize(o.size) + '</td>';\n msg += '<td>';\n switch (o.status) {\n case PHOCOA.widgets.{$this->id}.status.READY:\n break;\n case PHOCOA.widgets.{$this->id}.status.UPLOADING:\n var pct = Math.round(100 * o.sizeProgress / o.size);\n msg += ' progress: ' + pct + '%';\n break;\n case PHOCOA.widgets.{$this->id}.status.COMPLETE:\n if (o.error)\n {\n msg += ' Error uploading: ' + o.resultMessage;\n }\n else\n {\n msg += ' Uploaded.';\n }\n break;\n }\n msg += '</td>';\n msg += '</tr>';\n return msg;\n }).join('') + '</table>');\n };\n "; return $html; }
function initJS($blockContent) { $myAutoCompleteContainer = "WFYAHOO_widget_AutoComplete_{$this->id}_autocomplete"; $html = "\n PHOCOA.widgets.{$this->id}.init = function() {\n "; switch ($this->datasource) { case WFYAHOO_widget_AutoComplete::DATASOURCE_JS_ARRAY: $html .= "var jsDSArray = ["; $first = true; // we allow $multiColumnData = false; foreach ($this->datasourceJSArray as $item) { if ($first) { $first = false; if (is_array($item)) { $multiColumnData = true; } } else { $html .= ", "; } if ($multiColumnData) { $subItems = $item; array_walk($subItems, create_function('&$v,$k', '$v = \'"\' . str_replace(\'"\', \'\\"\', $v) . \'"\';')); $html .= '[' . join(',', $subItems) . ']'; } else { $html .= '"' . str_replace('"', '\\"', $item) . '"'; } } $html .= "];\n"; $html .= "var acDatasource = new YAHOO.widget.DS_JSArray(jsDSArray);"; break; case WFYAHOO_widget_AutoComplete::DATASOURCE_XHR: $html .= "\n // need to create a PHOCOA.RPC to get the URL for the query\n var acXHRRPC = new PHOCOA.WFRPC('" . WWW_ROOT . '/' . $this->page()->module()->invocation()->invocationPath() . "', '#page#{$this->id}', 'ajaxLoadData');\n "; $schema = array(); foreach ($this->dynamicDataLoaderSchema as $field) { $schema[] = array('key' => $field); } $html .= "\n var acDatasource = new YAHOO.util.XHRDataSource();\n acDatasource.responseType = YAHOO.util.XHRDataSource.TYPE_JSON;\n acDatasource.responseSchema = {\n resultsList: 'results',\n fields: " . WFJSON::encode($schema) . "\n };\n "; break; default: throw new WFException("Unsupported datasource type."); } // add properties to datasource $html .= $this->jsForSimplePropertyConfig('acDatasource', 'maxCacheEntries', $this->datasourceMaxCacheEntries); // set up widget $html .= "\nvar AutoCompleteWidget = new YAHOO.widget.AutoComplete('{$this->id}','{$myAutoCompleteContainer}', acDatasource);\n"; $html .= "\nAutoCompleteWidget.queryQuestionMark = false;\n"; if ($this->datasource === WFYAHOO_widget_AutoComplete::DATASOURCE_XHR) { $html .= "\n\nvar urlGenerator = function(query) {\n query = decodeURIComponent(query); // YUI has already encoded this, but we will encode it too via PHOCOA, so we need to undo theirs to avoid encoding issues\n var phocoaArgs = [query];\n if (PHOCOA.widgets['{$this->id()}'] && PHOCOA.widgets['{$this->id()}'].yuiDelegate && PHOCOA.widgets['{$this->id()}'].yuiDelegate.dynamicDataLoaderCollectArguments)\n {\n phocoaArgs.push(PHOCOA.widgets['{$this->id()}'].yuiDelegate.dynamicDataLoaderCollectArguments());\n }\n phocoaArgs = phocoaArgs.flatten();\n var url = acXHRRPC.actionAsURL(phocoaArgs);\n return url;\n};\nAutoCompleteWidget.generateRequest = urlGenerator;\n"; } $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'animVert', $this->animVert); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'animHoriz', $this->animHoriz); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'animSpeed', $this->animSpeed); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'queryMatchCase', $this->datasourceQueryMatchCase); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'queryMatchContains', $this->datasourceQueryMatchContains); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'queryMatchSubset', $this->datasourceQueryMatchSubset); // calculate delimiter $delimJs = NULL; if (is_array($this->delimChar)) { $delimJs = '['; $first = true; foreach ($this->delimChar as $c) { if ($first) { $first = false; } else { $delimJs .= ', '; } $delimJs .= "'{$c}'"; } $delimJs .= ']'; } else { if ($this->delimChar) { $delimJs = "'{$this->delimChar}'"; } } if ($delimJs) { $html .= "\nAutoCompleteWidget.delimChar = {$delimJs};\n"; } $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'maxResultsDisplayed', $this->maxResultsDisplayed); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'minQueryLength', $this->minQueryLength); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'queryDelay', $this->queryDelay); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'autoHighlight', $this->autoHighlight); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'highlightClassName', $this->highlightClassName); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'prehighlightClassName', $this->prehighlightClassName); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'useShadow', $this->useShadow); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'useIFrame', $this->IFrame); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'forceSelection', $this->forceSelection); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'typeAhead', $this->typeAhead); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'allowBrowserAutocomplete', $this->allowBrowserAutocomplete); $html .= $this->jsForSimplePropertyConfig('AutoCompleteWidget', 'alwaysShowContainer', $this->alwaysShowContainer); if ($this->enableToggleButton) { $html .= <<<END var bToggler = YAHOO.util.Dom.get("{$this->id}_acToggle"); var oPushButtonB = new YAHOO.widget.Button({container:bToggler}); oPushButtonB.on("click", function(e) { if(!YAHOO.util.Dom.hasClass(bToggler, "open")) { YAHOO.util.Dom.addClass(bToggler, "open") } // Is open if(AutoCompleteWidget.isContainerOpen()) { AutoCompleteWidget.collapseContainer(); } // Is closed else { AutoCompleteWidget.getInputEl().focus(); // Needed to keep widget active setTimeout(function() { // For IE AutoCompleteWidget.sendQuery(""); },0); } }); AutoCompleteWidget.containerCollapseEvent.subscribe(function(){YAHOO.util.Dom.removeClass(bToggler, "open")}); END; } $html .= "\nPHOCOA.runtime.addObject(AutoCompleteWidget, '{$this->id}');\n"; $html .= "\n};"; return $html; }